Better support for customising context lines in --patch commands
cover Better support for customising context lines in --patch commands
This series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"
The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Leon Michalak (3):
add-patch: respect diff.context configuration
add-patch: add diff.context command line overrides
add-interactive: add new "context" subcommand
Documentation/git-add.adoc | 21 ++++++- Documentation/git-checkout.adoc | 11 ++++ Documentation/git-commit.adoc | 11 ++++ Documentation/git-reset.adoc | 11 ++++ Documentation/git-restore.adoc | 11 ++++ Documentation/git-stash.adoc | 11 ++++ add-interactive.c | 107 +++++++++++++++++++++++++++++--- add-interactive.h | 17 ++++- add-patch.c | 11 +++- builtin/add.c | 21 +++++-- builtin/checkout.c | 28 ++++++++- builtin/commit.c | 15 ++++- builtin/reset.c | 16 ++++- builtin/stash.c | 54 ++++++++++++---- commit.h | 3 +- t/t3701-add-interactive.sh | 36 +++++++++-- t/t4055-diff-context.sh | 78 ++++++++++++++++++++++- t/t9902-completion.sh | 2 + 18 files changed, 420 insertions(+), 44 deletions(-)
base-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1915%2FNinjaInShade%2Finteractive-patch-context-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1915/NinjaInShade/interactive-patch-context-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1915
Signature · 1 line
gitgitgadget
PATCH 1/3 add-patch: respect diff.context configuration
From: Leon Michalak <[email protected]>
This aims to teach relevant builtins (that take in --patch) to respect the user's diff.context and diff.interHunkContext file configurations.
Since these are both UI options and --patch is designed for the end user, I believe this was previously just an inconsistency, which this patch hopes to address.
--- add-interactive.c | 16 ++++++++++---- add-patch.c | 6 ++++++ t/t4055-diff-context.sh | 48 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 5 deletions(-)
add-interactive.c +12 -4
@@ -41,6 +41,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)const char *value; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;
@@ -78,6 +80,9 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +repo_config_get_int (r,"diff.context" , &s->context); +repo_config_get_int (r,"diff.interHunkContext" , &s->interhunkcontext); +repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL );
@@ -1014,10 +1019,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; -strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" , -oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), -"--" ,NULL ); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );for (i =0 ; i < files->items.nr; i++)if (files->selected[i]) strvec_push(&cmd.args,
add-patch.c +6 -0
@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) {struct strvec args =STRVEC_INIT ;const char *diff_algorithm = s->s.interactive_diff_algorithm; +int diff_context = s->s.context; +int diff_interhunkcontext = s->s.interhunkcontext;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;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)int res;strvec_pushv (&args, s->mode->diff_cmd); +if (diff_context !=-1 ) +strvec_pushf (&args,"--unified=%i" , diff_context); +if (diff_interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , diff_interhunkcontext);if (diff_algorithm)strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm);if (s->revision) {
t/t4055-diff-context.sh +47 -1
54 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH 2/3 add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
This patch compliments 8b91eef812, 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.
--- Documentation/git-add.adoc | 11 +++++++ Documentation/git-checkout.adoc | 11 +++++++ Documentation/git-commit.adoc | 11 +++++++ Documentation/git-reset.adoc | 11 +++++++ Documentation/git-restore.adoc | 11 +++++++ Documentation/git-stash.adoc | 11 +++++++ add-interactive.c | 19 +++++++++--- add-interactive.h | 17 +++++++++-- add-patch.c | 5 +-- builtin/add.c | 21 ++++++++++--- builtin/checkout.c | 28 +++++++++++++++-- builtin/commit.c | 15 ++++++++- builtin/reset.c | 16 ++++++++-- builtin/stash.c | 54 ++++++++++++++++++++++++++------- commit.h | 3 +- t/t4055-diff-context.sh | 30 ++++++++++++++++++ t/t9902-completion.sh | 2 ++ 17 files changed, 245 insertions(+), 31 deletions(-)
Documentation/git-add.adoc +11 -0
@@ -104,6 +104,17 @@ This effectively runs `add --interactive`, but bypasses the initial command menu and directly jumps to the `patch` subcommand. See ``Interactive mode'' for details. +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--interactive/--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--interactive/--patch`. + `-e`:: `--edit`:: Open the diff vs. the index in an editor and let the user
Documentation/git-checkout.adoc +11 -0
@@ -289,6 +289,17 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--patch`. + --ignore-other-worktrees:: `git checkout` refuses when the wanted branch is already checked out or otherwise in use by another worktree. This option makes
Documentation/git-commit.adoc +11 -0
@@ -76,6 +76,17 @@ OPTIONS which changes to commit. See linkgit:git-add[1] for details. +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--interactive/--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--interactive/--patch`. + `-C <commit>`:: `--reuse-message=<commit>`:: Take an existing _<commit>_ object, and reuse the log message
Documentation/git-reset.adoc +11 -0
@@ -125,6 +125,17 @@ OPTIONS separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--patch`. + `--`:: Do not interpret any more arguments as options.
Documentation/git-restore.adoc +11 -0
@@ -52,6 +52,17 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--patch`. + `-W`:: `--worktree`:: `-S`::
Documentation/git-stash.adoc +11 -0
@@ -208,6 +208,17 @@ to learn how to operate the `--patch` mode. The `--patch` option implies `--keep-index`. You can use `--no-keep-index` to override this. +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--patch`. + -S:: --staged:: This option is only valid for `push` and `save` commands.
add-interactive.c +15 -4
@@ -36,7 +36,8 @@ static void init_color(struct repository *r, struct add_i_state *s,free (key); } -void init_add_i_state (struct add_i_state *s,struct repository *r) +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt) {const char *value;
@@ -86,6 +87,11 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); + +if (add_p_opt->context !=-1 ) + s->context = add_p_opt->context; +if (add_p_opt->interhunkcontext !=-1 ) + s->interhunkcontext = add_p_opt->interhunkcontext; }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, opts->prompt =N_ ("Patch update" ); count =list_and_choose (s, files, opts);if (count >0 ) { +struct add_p_opt add_p_opt = { + .context = s->context, + .interhunkcontext = s->interhunkcontext, + };struct strvec args =STRVEC_INIT ;struct pathspec ps_selected = {0 };
@@ -984,7 +994,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,parse_pathspec (&ps_selected,PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL ,PATHSPEC_LITERAL_PATH ,"" , args.v); - res =run_add_p (s->r,ADD_P_ADD ,NULL , &ps_selected); + res =run_add_p (s->r,ADD_P_ADD , &add_p_opt,NULL , &ps_selected);strvec_clear (&args);clear_pathspec (&ps_selected); }
@@ -1118,7 +1128,8 @@ static void command_prompt_help(struct add_i_state *s) _("(empty) select nothing")); } -int run_add_i (struct repository *r,const struct pathspec *ps) +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt) {struct add_i_state s = {NULL };struct print_command_item_data data = {"[" ,"]" };
@@ -1161,7 +1172,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps) ->util = util; } -init_add_i_state (&s, r); +init_add_i_state (&s, r, add_p_opt);/* * When color was asked for, use the prompt color for
add-interactive.h +14 -3
@@ -3,6 +3,13 @@#include "color.h" +#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 } + +struct add_p_opt { +int context; +int interhunkcontext; +}; +struct add_i_state {struct repository *r;int use_color;
@@ -18,14 +25,17 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; }; -void init_add_i_state (struct add_i_state *s,struct repository *r); +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt);void clear_add_i_state (struct add_i_state *s);struct repository ;struct pathspec ; -int run_add_i (struct repository *r,const struct pathspec *ps); +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt);enum add_p_mode {ADD_P_ADD ,
@@ -36,6 +46,7 @@ enum add_p_mode { };int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps); +struct add_p_opt *o,const char *revision, +const struct pathspec *ps);#endif
add-patch.c +3 -2
@@ -1766,14 +1766,15 @@ soft_increment: }int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps) +struct add_p_opt *o,const char *revision, +const struct pathspec *ps) {struct add_p_state s = { { r },STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT };size_t i, binary_count =0 ; -init_add_i_state (&s.s, r); +init_add_i_state (&s.s, r, o);if (mode ==ADD_P_STASH ) s.mode = &patch_mode_stash;
builtin/add.c +17 -4
@@ -29,6 +29,7 @@ static const char * const builtin_add_usage[] = { NULL };static int patch_interactive, add_interactive, edit_interactive; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int take_worktree_changes;static int add_renormalize;static int pathspec_file_nul;
@@ -157,7 +158,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch) +int patch,struct add_p_opt *add_p_opt) {struct pathspec pathspec;int ret;
@@ -169,9 +170,10 @@ int interactive_add(struct repository *repo, prefix, argv);if (patch) - ret = !!run_add_p (repo,ADD_P_ADD ,NULL , &pathspec); + ret = !!run_add_p (repo,ADD_P_ADD , add_p_opt,NULL , + &pathspec);else - ret = !!run_add_i (repo, &pathspec); + ret = !!run_add_i (repo, &pathspec, add_p_opt);clear_pathspec (&pathspec);return ret;
@@ -253,6 +255,12 @@ static struct option builtin_add_options[] = {OPT_GROUP ("" ),OPT_BOOL ('i' ,"interactive" , &add_interactive,N_ ("interactive picking" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("select hunks interactively" )), +OPT_INTEGER_F ('U' ,"unified" , &add_p_opt.context, +N_ ("generate diffs with <n> lines context, implies --interactive/--patch" ), +PARSE_OPT_NONEG ), +OPT_INTEGER_F (0 ,"inter-hunk-context" , &add_p_opt.interhunkcontext, +N_ ("show context between diff hunks up to the specified number of lines, implies --interactive/--patch" ), +PARSE_OPT_NONEG ),OPT_BOOL ('e' ,"edit" , &edit_interactive,N_ ("edit current diff and apply" )),OPT__FORCE (&ignored_too,N_ ("allow adding otherwise ignored files" ),0 ), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -398,7 +406,12 @@ int cmd_add(int argc,die (_ ("options '%s' and '%s' cannot be used together" ),"--dry-run" ,"--interactive/--patch" );if (pathspec_from_file)die (_ ("options '%s' and '%s' cannot be used together" ),"--pathspec-from-file" ,"--interactive/--patch" ); -exit (interactive_add (repo, argv +1 , prefix, patch_interactive)); +exit (interactive_add (repo, argv +1 , prefix, patch_interactive, &add_p_opt)); + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }if (edit_interactive) {
builtin/checkout.c +25 -3
@@ -61,6 +61,8 @@ static const char * const restore_usage[] = {struct checkout_opts {int patch_mode; +int patch_context; +int patch_interhunk_context;int quiet;int merge;int force;
@@ -104,7 +106,12 @@ struct checkout_opts {struct tree *source_tree; }; -#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 } +#define CHECKOUT_OPTS_INIT { \ + .conflict_style = -1, \ + .merge = -1, \ + .patch_context = -1, \ + .patch_interhunk_context = -1, \ +}struct branch_info {char *name;/* The short name used */
@@ -539,6 +546,10 @@ static int checkout_paths(const struct checkout_opts *opts,if (opts->patch_mode) {enum add_p_mode patch_mode; +struct add_p_opt add_p_opt = { + .context = opts->patch_context, + .interhunkcontext = opts->patch_interhunk_context, + };const char *rev = new_branch_info->name;char rev_oid[GIT_MAX_HEXSZ +1 ];
@@ -564,8 +575,13 @@ static int checkout_paths(const struct checkout_opts *opts,else BUG ("either flag must have been set, worktree=%d, index=%d" , opts->checkout_worktree, opts->checkout_index); -return !!run_add_p (the_repository, patch_mode, rev, - &opts->pathspec); +return !!run_add_p (the_repository, patch_mode, &add_p_opt, + rev, &opts->pathspec); + }else { +if (opts->patch_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (opts->patch_interhunk_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }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, N_("checkout their version for unmerged files"), 3, PARSE_OPT_NONEG),OPT_BOOL ('p' ,"patch" , &opts->patch_mode,N_ ("select hunks interactively" )), +OPT_INTEGER_F ('U' ,"unified" , &opts->patch_context, +N_ ("generate diffs with <n> lines context, implies --patch" ), +PARSE_OPT_NONEG ), +OPT_INTEGER_F (0 ,"inter-hunk-context" , &opts->patch_interhunk_context, +N_ ("show context between diff hunks up to the specified number of lines, implies --patch" ), +PARSE_OPT_NONEG ),OPT_BOOL (0 ,"ignore-skip-worktree-bits" , &opts->ignore_skipworktree,N_ ("do not limit pathspecs to sparse entries only" )), OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
builtin/commit.c +14 -1
@@ -19,6 +19,7 @@#include "environment.h" #include "diff.h" #include "commit.h" +#include "add-interactive.h" #include "gettext.h" #include "revision.h" #include "wt-status.h"
@@ -122,6 +123,7 @@ static const char *edit_message, *use_message;static char *fixup_message, *fixup_commit, *squash_message;static const char *fixup_prefix;static int all, also, interactive, patch_interactive, only, amend, signoff; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int edit_flag =-1 ;/* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */
@@ -400,7 +402,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env =xstrdup_or_null (getenv (INDEX_ENVIRONMENT ));setenv (INDEX_ENVIRONMENT , the_repository->index_file,1 ); -if (interactive_add (the_repository, argv, prefix, patch_interactive) !=0 ) +if (interactive_add (the_repository, argv, prefix, patch_interactive, &add_p_opt) !=0 )die (_ ("interactive add failed" )); the_repository->index_file = old_repo_index_file;
@@ -424,6 +426,11 @@ static const char *prepare_index(const char **argv, const char *prefix, commit_style =COMMIT_NORMAL ; ret =get_lock_file_path (&index_lock); goto out; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }/*
@@ -1722,6 +1729,12 @@ int cmd_commit(int argc,OPT_BOOL ('i' ,"include" , &also,N_ ("add specified files to index for commit" )),OPT_BOOL (0 ,"interactive" , &interactive,N_ ("interactively add files" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("interactively add changes" )), +OPT_INTEGER_F ('U' ,"unified" , &add_p_opt.context, +N_ ("generate diffs with <n> lines context, implies --interactive/--patch" ), +PARSE_OPT_NONEG ), +OPT_INTEGER_F (0 ,"inter-hunk-context" , &add_p_opt.interhunkcontext, +N_ ("show context between diff hunks up to the specified number of lines, implies --interactive/--patch" ), +PARSE_OPT_NONEG ),OPT_BOOL ('o' ,"only" , &only,N_ ("commit only specified files" )),OPT_BOOL ('n' ,"no-verify" , &no_verify,N_ ("bypass pre-commit and commit-msg hooks" )), OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
builtin/reset.c +14 -2
@@ -346,6 +346,7 @@ int cmd_reset(int argc,struct object_id oid;struct pathspec pathspec;int intent_to_add =0 ; +struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;const struct option options[] = {OPT__QUIET (&quiet,N_ ("be quiet, only report errors" )), OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -370,6 +371,12 @@ int cmd_reset(int argc, PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),OPT_BOOL ('p' ,"patch" , &patch_mode,N_ ("select hunks interactively" )), +OPT_INTEGER_F ('U' ,"unified" , &add_p_opt.context, +N_ ("generate diffs with <n> lines context, implies --patch" ), +PARSE_OPT_NONEG ), +OPT_INTEGER_F (0 ,"inter-hunk-context" , &add_p_opt.interhunkcontext, +N_ ("show context between diff hunks up to the specified number of lines, implies --patch" ), +PARSE_OPT_NONEG ),OPT_BOOL ('N' ,"intent-to-add" , &intent_to_add,N_ ("record only the fact that removed paths will be added later" )), OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -424,9 +431,14 @@ int cmd_reset(int argc,if (reset_type !=NONE )die (_ ("options '%s' and '%s' cannot be used together" ),"--patch" ,"--{hard,mixed,soft}" );trace2_cmd_mode ("patch-interactive" ); - update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , rev, - &pathspec); + update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , + &add_p_opt, rev, &pathspec); goto cleanup; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }/* git reset tree [--] paths... can be used to
builtin/stash.c +43 -11
134 lines not on this page · raw message
commit.h +2 -1
@@ -2,6 +2,7 @@#define COMMIT_H #include "object.h" +#include "add-interactive.h" struct signature_check ;struct strbuf ;
@@ -257,7 +258,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch); +int patch,struct add_p_opt *add_p_opt);struct commit_extra_header {struct commit_extra_header *next;
t/t4055-diff-context.sh +30 -0
@@ -104,6 +104,36 @@ test_expect_success 'The -U option overrides diff.context' ' ! grep "^ firstline" output ' +test_expect_success 'The -U option overrides diff.context for "add"' ' + git config diff.context 8 && + git add -U4 -p >output && + ! grep "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "commit"' ' + git config diff.context 8 && + ! git commit -U4 -p >output && + ! grep "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "checkout"' ' + git config diff.context 8 && + git checkout -U4 -p >output && + ! grep "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "stash"' ' + git config diff.context 8 && + ! git stash -U4 -p >output && + ! grep "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "restore"' ' + git config diff.context 8 && + git restore -U4 -p >output && + ! grep "^ firstline" output +' + test_expect_success 'diff.context honored by "diff"' ' git config diff.context 8 && git diff >output &&
t/t9902-completion.sh +2 -0
@@ -2596,6 +2596,8 @@ test_expect_success 'double dash "git checkout"' ' --merge Z --conflict=Z --patch Z + --unified=Z + --inter-hunk-context=Z --ignore-skip-worktree-bits Z --ignore-other-worktrees Z --recurse-submodules Z
Signature · 1 line
gitgitgadget
PATCH 3/3 add-interactive: add new "context" subcommand
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
This teaches add/commit --interactive a new "context" subcommand, which changes the amount of context lines subsequent subcommands like "patch" or "diff" generate in their diffs.
--- Documentation/git-add.adoc | 10 ++++-- add-interactive.c | 72 +++++++++++++++++++++++++++++++++++++- t/t3701-add-interactive.sh | 36 ++++++++++++++++--- 3 files changed, 110 insertions(+), 8 deletions(-)
Documentation/git-add.adoc +8 -2
@@ -265,14 +265,15 @@ and type return, like this: ------------ *** Commands *** 1: status 2: update 3: revert 4: add untracked - 5: patch 6: diff 7: quit 8: help + 5: patch 6: diff 7: context 8: quit + 9: help What now> 1 ------------ You also could say `s` or `sta` or `status` above as long as the choice is unique. -The main command loop has 6 subcommands (plus help and quit). +The main command loop has 7 subcommands (plus help and quit). status::
@@ -373,6 +374,11 @@ diff:: This lets you review what will be committed (i.e. between `HEAD` and index). +context:: + + This lets you change the amount of context lines shown in diffs that + the 'patch' and 'diff' subcommands generate. + EDITING PATCHES ---------------
add-interactive.c +71 -1
108 lines not on this page · raw message
t/t3701-add-interactive.sh +31 -5
@@ -758,16 +758,19 @@ test_expect_success 'colors can be overridden' ' <RED>*** Commands ***<RESET> 1: <YELLOW>s<RESET>tatus 2: <YELLOW>u<RESET>pdate 3: <YELLOW>r<RESET>evert 4: <YELLOW>a<RESET>dd untracked - 5: <YELLOW>p<RESET>atch 6: <YELLOW>d<RESET>iff 7: <YELLOW>q<RESET>uit 8: <YELLOW>h<RESET>elp + 5: <YELLOW>p<RESET>atch 6: <YELLOW>d<RESET>iff 7: <YELLOW>c<RESET>ontext 8: <YELLOW>q<RESET>uit + 9: <YELLOW>h<RESET>elp <YELLOW>What now<RESET>> <GREEN>status - show paths with changes<RESET> <GREEN>update - add working tree state to the staged set of changes<RESET> <GREEN>revert - revert staged set of changes back to the HEAD version<RESET> <GREEN>patch - pick hunks and update selectively<RESET> <GREEN>diff - view diff between HEAD and index<RESET> + <GREEN>context - change how many context lines diffs are generated with<RESET> <GREEN>add untracked - add contents of untracked files to the staged set of changes<RESET> <RED>*** Commands ***<RESET> 1: <YELLOW>s<RESET>tatus 2: <YELLOW>u<RESET>pdate 3: <YELLOW>r<RESET>evert 4: <YELLOW>a<RESET>dd untracked - 5: <YELLOW>p<RESET>atch 6: <YELLOW>d<RESET>iff 7: <YELLOW>q<RESET>uit 8: <YELLOW>h<RESET>elp + 5: <YELLOW>p<RESET>atch 6: <YELLOW>d<RESET>iff 7: <YELLOW>c<RESET>ontext 8: <YELLOW>q<RESET>uit + 9: <YELLOW>h<RESET>elp <YELLOW>What now<RESET>> Bye. EOF test_cmp expect actual &&
@@ -831,7 +834,8 @@ test_expect_success 'brackets appear without color' ' | |*** Commands *** | 1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked - | 5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp + | 5: [p]atch 6: [d]iff 7: [c]ontext 8: [q]uit + | 9: [h]elp |What now> Bye. EOF
@@ -1172,16 +1176,19 @@ test_expect_success 'show help from add--helper' ' <BOLD>*** Commands ***<RESET> 1: <BOLD;BLUE>s<RESET>tatus 2: <BOLD;BLUE>u<RESET>pdate 3: <BOLD;BLUE>r<RESET>evert 4: <BOLD;BLUE>a<RESET>dd untracked - 5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>q<RESET>uit 8: <BOLD;BLUE>h<RESET>elp + 5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>c<RESET>ontext 8: <BOLD;BLUE>q<RESET>uit + 9: <BOLD;BLUE>h<RESET>elp <BOLD;BLUE>What now<RESET>> <BOLD;RED>status - show paths with changes<RESET> <BOLD;RED>update - add working tree state to the staged set of changes<RESET> <BOLD;RED>revert - revert staged set of changes back to the HEAD version<RESET> <BOLD;RED>patch - pick hunks and update selectively<RESET> <BOLD;RED>diff - view diff between HEAD and index<RESET> + <BOLD;RED>context - change how many context lines diffs are generated with<RESET> <BOLD;RED>add untracked - add contents of untracked files to the staged set of changes<RESET> <BOLD>*** Commands ***<RESET> 1: <BOLD;BLUE>s<RESET>tatus 2: <BOLD;BLUE>u<RESET>pdate 3: <BOLD;BLUE>r<RESET>evert 4: <BOLD;BLUE>a<RESET>dd untracked - 5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>q<RESET>uit 8: <BOLD;BLUE>h<RESET>elp + 5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>c<RESET>ontext 8: <BOLD;BLUE>q<RESET>uit + 9: <BOLD;BLUE>h<RESET>elp <BOLD;BLUE>What now<RESET>>$SP Bye. EOF
@@ -1230,4 +1237,23 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'change context works' ' + git reset --hard && + cat >template <<-\EOF && + firstline + preline + TARGET + postline + lastline + EOF + sed "/TARGET/d" >x <template && + git update-index --add x && + git commit -m initial && + sed "s/TARGET/ADDED/" >x <template && + test_write_lines p 1 | git add -i >output && + grep firstline output && + test_write_lines c 0 p 1 | git add -i >output && + ! grep firstline output +' + test_done
Signature · 1 line
gitgitgadget
Re: [PATCH 2/3] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetQuoted 5 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments
8b91eef812, where builtins that accept--patchoptions now respectdiff.contextanddiff.interHunkContextfile configurations.
8b91eef812 is patch 1. This hash will change once the patches have been imported via git-am(1). So it won’t make sense when these patches land as commits.
I think the usual approach is to refer to a previous commit in the series as “in a previous commit we...”. Or maybe “in the previous commit” for this patch and “two commits ago” for patch 3.
For commits that are in the stable history (like master) the convention is to use:
git show -s --pretty=reference <commit>
Without backticks (`). See SubmittingPatches, commit-reference.
Re: [PATCH 2/3] add-patch: add diff.context command line overrides
In reply to a message not in the archiveThanks! Part of me did wonder if the reference would be updated when merging, but I can see now the correct way to approach this.
This being my first ever contribution, I hope I am at least a little forgiven for any mistakes, which of course I'm more than happy to correct and learn from.
Quoted 29 lines · Leon Michalak
Thanks! Part of me did wonder if the reference would be updated when merging, but I can see now the correct way to approach this.
This being my first ever contribution, I hope I am at least a little forgiven for any mistakes, which of course I can correct :)
Quoted 22 lines · On Mon, 5 May 2025, 10:50 Kristoffer Haugsbakk…
Quoted 5 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments
8b91eef812, where builtins that accept--patchoptions now respectdiff.contextanddiff.interHunkContextfile configurations.
8b91eef812is patch 1. This hash will change once the patches have been imported via git-am(1). So it won’t make sense when these patches land as commits.I think the usual approach is to refer to a previous commit in the series as “in a previous commit we...”. Or maybe “in the previous commit” for this patch and “two commits ago” for patch 3.
For commits that are in the stable history (like
master) the convention is to use:git show -s --pretty=reference <commit>Without backticks (`). See SubmittingPatches, commit-reference.
Re: [PATCH 1/3] add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetQuoted 17 lines · Leon Michalak via GitGitGadget
This aims to teach relevant builtins (that take in
--patch) to respect the user's diff.context and diff.interHunkContext file configurations.Since these are both UI options and
--patchis designed for the end user, I believe this was previously just an inconsistency, which this patch hopes to address.Signed-off-by Leon Michalak <[email protected]>---
t/t4055-diff-context.sh +2
-1@@ -49,7 +49,53 @@ test_expect_success 'diff.context honored by "log"' ' ! grep firstline output && git config diff.context 8 && git log -1 -p >output && - grep "^ firstline" output + grep "^ firstline" output && + git config --unset diff.context
t/t4055-diff-context.sh test_expect_success 'diff.context honored by "log"' ' · line 63
Quoted 10 lines
t/t4055-diff-context.sh +10
-0+' + +test_expect_success 'diff.context honored by "add"' ' + git add -p >output && + ! grep firstline output && + git config diff.context 8 && + git add -p >output && + grep "^ firstline" output && + git config --unset diff.context +'
Be aware that if any command in the &&-chain prior to git config --unset fails, then git config --unset itself will not be executed, hence the cleanup won't happen. The way to address this is to instead use test_config to configure the value since it will ensure that the value gets "unset" regardless of whether the test succeeds or fails:
test_config diff.context 8 &&
The same comment applies to all the new tests.
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
In reply to Leon Michalak via GitGitGadgetQuoted 8 lines · Leon Michalak via GitGitGadget
This teaches
add/commit --interactivea new "context" subcommand, which changes the amount of context lines subsequent subcommands like "patch" or "diff" generate in their diffs.Signed-off-by Leon Michalak <[email protected]>---
Documentation/git-add.adoc and type return, like this: · line 270
Quoted 7 lines
Documentation/git-add.adoc +2
-1@@ -265,14 +265,15 @@ and type return, like this: ------------ *** Commands *** 1: status 2: update 3: revert 4: add untracked - 5: patch 6: diff 7: quit 8: help + 5: patch 6: diff 7: context 8: quit + 9: help What now> 1
I'm not a `git add/commit --interactive' user, but I can imagine that inserting "context" at 7 and bumping "quit" and "help" to 8 and 9, respectively, is going to play havoc with muscle memory people have built up over the years. To make this more friendly for existing users, I'd suggest adding this new command at the end of the list without changing the existing command numbers.
Also, looking at this list, I can't help but think that "context" feels out of place among the other action-oriented commands. Moreover, if --interactive mode grows more configuration/setting-like commands in the future, do we really want to keep extending this menu for them? Specifically, I'm wondering if it would instead make sense to introduce a new item "9: settings" which takes the user to a "Settings" submenu from which the number of context lines can be set.
Documentation/git-add.adoc and type return, like this: · line 276
Quoted 2 lines
Documentation/git-add.adoc +1
-1-The main command loop has 6 subcommands (plus help and quit). +The main command loop has 7 subcommands (plus help and quit).
Since you're touching this anyhow, let's fix this maintenance burden once and for all by writing more it generically, perhaps like this:
The main command loop has several subcommands (plus help and quit).
Documentation/git-add.adoc diff:: · line 380
Quoted 4 lines
Documentation/git-add.adoc +4
-0+context:: + + This lets you change the amount of context lines shown in diffs that + the 'patch' and 'diff' subcommands generate.
s/amount/number/
add-interactive.c static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED, · line 1119
Quoted 4 lines
add-interactive.c +2
-0@@ -1061,6 +1118,8 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED, +color_fprintf_ln (stdout, s->help_color,"context - %s" , +_ ("change how many context lines diffs are generated with" ));
Perhaps:
_("change the number of diff context lines"));add-interactive.c static void choose_prompt_help(struct add_i_state *s) · line 1151
Quoted 7 lines
add-interactive.c +6
-0@@ -1087,6 +1146,16 @@ static void choose_prompt_help(struct add_i_state *s) +static void choose_prompt_help_context (struct add_i_state *s) +{ +color_fprintf_ln (stdout, s->help_color,"%s" , +_ ("Prompt help:" )); +color_fprintf_ln (stdout, s->help_color,"<n> - %s" , +_ ("specify new context lines amount" ));
Likewise:
_("change number of diff context lines"));add-interactive.c static void choose_prompt_help(struct add_i_state *s) · line 1156
Quoted 2 lines
add-interactive.c +2
-0+color_fprintf_ln (stdout, s->help_color," - %s" , +_ ("(empty) finish selecting" ));
"finish selecting" looks like a copy/paste error from elsewhere in this source file. Perhaps you meant something like:
_("(empty) don't change number of context lines"));Quoted 10 lines
t/t3701-add-interactive.sh +8
-0@@ -1230,4 +1237,23 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' +test_expect_success 'change context works' ' + git reset --hard && + cat >template <<-\EOF && + firstline + preline + TARGET + postline + lastline
t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1254
Quoted 10 lines
t/t3701-add-interactive.sh +10
-0+ EOF + sed "/TARGET/d" >x <template && + git update-index --add x && + git commit -m initial && + sed "s/TARGET/ADDED/" >x <template && + test_write_lines p 1 | git add -i >output && + grep firstline output && + test_write_lines c 0 p 1 | git add -i >output && + ! grep firstline output +'
This script does have its share of bare grep invocations, but these days we prefer test_grep, which also appears often in this script, so the following would be more appropriate:
test_grep firstline output &&
...
test_grep ! firstline outputNote the placement of "!" when used with test_grep.
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
Valid points, I don't think I have any objections to anything listed.
Would it be recommended to update to test_grep (and test_config from previous message) in the same test files whilst I'm at it?
Thanks for the review :)
Quoted 108 lines · Eric Sunshine
Quoted 8 lines · Leon Michalak via GitGitGadget
This teaches
add/commit --interactivea new "context" subcommand, which changes the amount of context lines subsequent subcommands like "patch" or "diff" generate in their diffs.Signed-off-by Leon Michalak <[email protected]>---
Documentation/git-add.adoc and type return, like this: · line 270
Quoted 7 lines
Documentation/git-add.adoc +2
-1@@ -265,14 +265,15 @@ and type return, like this: ------------ *** Commands *** 1: status 2: update 3: revert 4: add untracked - 5: patch 6: diff 7: quit 8: help + 5: patch 6: diff 7: context 8: quit + 9: help What now> 1I'm not a `git add/commit --interactive' user, but I can imagine that inserting "context" at 7 and bumping "quit" and "help" to 8 and 9, respectively, is going to play havoc with muscle memory people have built up over the years. To make this more friendly for existing users, I'd suggest adding this new command at the end of the list without changing the existing command numbers.
Also, looking at this list, I can't help but think that "context" feels out of place among the other action-oriented commands. Moreover, if --interactive mode grows more configuration/setting-like commands in the future, do we really want to keep extending this menu for them? Specifically, I'm wondering if it would instead make sense to introduce a new item "9: settings" which takes the user to a "Settings" submenu from which the number of context lines can be set.
Documentation/git-add.adoc and type return, like this: · line 276
Quoted 2 lines
Documentation/git-add.adoc +1
-1-The main command loop has 6 subcommands (plus help and quit). +The main command loop has 7 subcommands (plus help and quit).Since you're touching this anyhow, let's fix this maintenance burden once and for all by writing more it generically, perhaps like this:
The main command loop has several subcommands (plus help and quit).
Documentation/git-add.adoc diff:: · line 380
Quoted 4 lines
Documentation/git-add.adoc +4
-0+context:: + + This lets you change the amount of context lines shown in diffs that + the 'patch' and 'diff' subcommands generate.s/amount/number/
add-interactive.c static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED, · line 1119
Quoted 4 lines
add-interactive.c +2
-0@@ -1061,6 +1118,8 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED, +color_fprintf_ln (stdout, s->help_color,"context - %s" , +_ ("change how many context lines diffs are generated with" ));Perhaps:
_("change the number of diff context lines"));add-interactive.c static void choose_prompt_help(struct add_i_state *s) · line 1151
Quoted 7 lines
add-interactive.c +6
-0@@ -1087,6 +1146,16 @@ static void choose_prompt_help(struct add_i_state *s) +static void choose_prompt_help_context (struct add_i_state *s) +{ +color_fprintf_ln (stdout, s->help_color,"%s" , +_ ("Prompt help:" )); +color_fprintf_ln (stdout, s->help_color,"<n> - %s" , +_ ("specify new context lines amount" ));Likewise:
_("change number of diff context lines"));add-interactive.c static void choose_prompt_help(struct add_i_state *s) · line 1156
Quoted 2 lines
add-interactive.c +2
-0+color_fprintf_ln (stdout, s->help_color," - %s" , +_ ("(empty) finish selecting" ));"finish selecting" looks like a copy/paste error from elsewhere in this source file. Perhaps you meant something like:
_("(empty) don't change number of context lines"));Quoted 10 lines
t/t3701-add-interactive.sh +8
-0@@ -1230,4 +1237,23 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' +test_expect_success 'change context works' ' + git reset --hard && + cat >template <<-\EOF && + firstline + preline + TARGET + postline + lastlinet/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1254
Quoted 10 lines
t/t3701-add-interactive.sh +10
-0+ EOF + sed "/TARGET/d" >x <template && + git update-index --add x && + git commit -m initial && + sed "s/TARGET/ADDED/" >x <template && + test_write_lines p 1 | git add -i >output && + grep firstline output && + test_write_lines c 0 p 1 | git add -i >output && + ! grep firstline output +'This script does have its share of bare
grepinvocations, but these days we prefertest_grep, which also appears often in this script, so the following would be more appropriate:test_grep firstline output && ... test_grep ! firstline outputNote the placement of "!" when used with
test_grep.
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
Quoted 2 lines · Leon Michalak
Valid points, I don't think I have any objections to anything listed.
Please don't "top post" and reply inline instead (see
https://en.wikipedia.org/wiki/Posting_style) as it's the standard on this list.
Quoted 2 lines
Would it be recommended to update to
test_grep(andtest_configfrom previous message) in the same test files whilst I'm at it?
If you want to replace pre existing "grep" commands with "test_grep" and pre existing git config with test_config, I would recommend doing it in preparatory patches that go first in your patch series.
Thanks!
Re: [PATCH 1/3] add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetHi Leon
Thanks for working on this. I've left a few comments below but for your first submission this is very good.
Quoted 4 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This aims to teach relevant builtins (that take in
--patch) to respect the user's diff.context and diff.interHunkContext file configurations.
This is a good summary of the intent of the patch. I'd maybe drop "This aims" and instead say that the various commands do not respect the config and this patch fixes that.
Quoted 25 lines
Since these are both UI options and
--patchis designed for the end user, I believe this was previously just an inconsistency, which this patch hopes to address.Signed-off-by Leon Michalak <[email protected]>--- add-interactive.c | 16 ++++++++++---- add-patch.c | 6 ++++++ t/t4055-diff-context.sh | 48 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 5 deletions(-)add-interactive.c +2
-0@@ -41,6 +41,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)const char *value; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 84
Quoted 5 lines
add-interactive.c +2
-0@@ -78,6 +80,9 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +repo_config_get_int (r,"diff.context" , &s->context); +repo_config_get_int (r,"diff.interHunkContext" , &s->interhunkcontext);
This looks good
add-interactive.c static int run_diff(struct add_i_state *s, const struct pathspec *ps, · line 1022
Quoted 9 lines
add-interactive.c +1
-4@@ -1014,10 +1019,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; -strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" , -oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), -"--" ,NULL ); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL );
As we're running "git diff" here nothing needs to be changed because it reads all of the relevant config variables itself. This is why the existing code does not worry about adding "--algorithm".
Quoted 14 lines
add-patch.c +2
-0@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) {struct strvec args =STRVEC_INIT ;const char *diff_algorithm = s->s.interactive_diff_algorithm; +int diff_context = s->s.context; +int diff_interhunkcontext = s->s.interhunkcontext;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;char *p, *pend, *colored_p =NULL , *colored_pend =NULL , marker ='\0' ;
add-patch.c static int parse_diff(struct add_p_state *s, const struct pathspec *ps) · line 432
Quoted 7 lines
add-patch.c +4
-0@@ -424,6 +426,10 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)int res;strvec_pushv (&args, s->mode->diff_cmd); +if (diff_context !=-1 ) +strvec_pushf (&args,"--unified=%i" , diff_context); +if (diff_interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , diff_interhunkcontext);
This is good - if the user has set diff.config or diff.interhunkcontext then we pass the appropriate values to "git diff-index" or "git diff-files" which unlike "git diff" do not read those config values themselves.
t/t4055-diff-context.sh
Quoted 7 lines
add-patch.c +0
-0if (diff_algorithm)strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm);if (s->revision) {t/t4055-diff-context.sh +0
-0
I'm not sure this is the best home for the new tests. Normally tests related to the code in add-patch.c go into t3701-add-interactive.sh
Quoted 6 lines
t/t4055-diff-context.sh +1
-1@@ -49,7 +49,53 @@ test_expect_success 'diff.context honored by "log"' ' ! grep firstline output && git config diff.context 8 && git log -1 -p >output && - grep "^ firstline" output + grep "^ firstline" output &&
t/t4055-diff-context.sh test_expect_success 'diff.context honored by "log"' ' · line 62
Quoted 10 lines
t/t4055-diff-context.sh +10
-0+ git config --unset diff.context +' + +test_expect_success 'diff.context honored by "add"' ' + git add -p >output && + ! grep firstline output && + git config diff.context 8 && + git add -p >output && + grep "^ firstline" output && + git config --unset diff.context
Eric has already mentioned using "test_config", I would go one step further and say that as we're only running a single command we should use "git add -c diff.context=* add -p" to avoid having to change the on disk config at all.
I would also recommend using "test_grep ..." rather than "grep ..." and "test_grep ! .." instead of "! grep ..." as they provide useful debugging information if the test fails.
Given the way the code is structured with the config being read in add-patch.c I'm not sure how much value there is in testing all the different "-p" commands. It would however be very useful to check that "git -c diff.interhunkcontext=8 add -p" works as expected.
I'll leave it there for now, I'll try and look at the other patches later today or maybe tomorrow.
Best Wishes
Phillip
Quoted 39 lines
t/t4055-diff-context.sh +36
-0+' + +test_expect_success 'diff.context honored by "commit"' ' + ! git commit -p >output && + ! grep firstline output && + git config diff.context 8 && + ! git commit -p >output && + grep "^ firstline" output && + git config --unset diff.context +' + +test_expect_success 'diff.context honored by "checkout"' ' + git checkout -p >output && + ! grep firstline output && + git config diff.context 8 && + git checkout -p >output && + grep "^ firstline" output && + git config --unset diff.context +' + +test_expect_success 'diff.context honored by "stash"' ' + ! git stash -p >output && + ! grep firstline output && + git config diff.context 8 && + ! git stash -p >output && + grep "^ firstline" output && + git config --unset diff.context +' + +test_expect_success 'diff.context honored by "restore"' ' + git restore -p >output && + ! grep firstline output && + git config diff.context 8 && + git restore -p >output && + grep "^ firstline" output && + git config --unset diff.context ' test_expect_success 'The -U option overrides diff.context' '
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
In reply to Eric SunshineQuoted 16 lines · Eric Sunshine
Quoted 14 lines · Leon Michalak via GitGitGadget
This teaches
add/commit --interactivea new "context" subcommand, which changes the amount of context lines subsequent subcommands like "patch" or "diff" generate in their diffs.Signed-off-by Leon Michalak <[email protected]>---
Documentation/git-add.adoc +2
-1@@ -265,14 +265,15 @@ and type return, like this: ------------ *** Commands *** 1: status 2: update 3: revert 4: add untracked - 5: patch 6: diff 7: quit 8: help + 5: patch 6: diff 7: context 8: quit + 9: help
Quoted 8 lines
Documentation/git-add.adoc and type return, like this: · line 270
Quoted 1 line
Documentation/git-add.adoc +0
-0What now> 1I'm not a `git add/commit --interactive' user, but I can imagine that inserting "context" at 7 and bumping "quit" and "help" to 8 and 9, respectively, is going to play havoc with muscle memory people have built up over the years. To make this more friendly for existing users, I'd suggest adding this new command at the end of the list without changing the existing command numbers.
Hmph, in the real UI, the first letters of these commands (which have deliberately been chosen to be unique) are shown in different color to hint that the answer to the prompt can be like 's' (for status). I would hate to see that quit/help, which are somewhat special, move from the very end position.
Perhaps the example of the documentation page shown above should respond with 's', not '1' to show more prominently that it is possible and encouraged? I dunno.
Quoted 4 lines
Also, looking at this list, I can't help but think that "context" feels out of place among the other action-oriented commands. Moreover, if --interactive mode grows more configuration/setting-like commands in the future, do we really want to keep extending this menu for them?
That is a valid concern.
Quoted 3 lines
Specifically, I'm wondering if it would instead make sense to introduce a new item "9: settings" which takes the user to a "Settings" submenu from which the number of context lines can be set.
's' is taken for 'status', so it shouldn't be '9: settings' (it should come before 'quit' instead), but I think I know where you are going.
An alternative that may work better is to allow subcommand specific parameters in the answer to the "What now>" prompt, e.g.
What now> r -U7
to choose an equivalent to "git revert -p -U7".
Thanks.
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
In reply to Christian CouderQuoted 3 lines · Christian Couder
Please don't "top post" and reply inline instead (see
https://en.wikipedia.org/wiki/Posting_style) as it's the standard on this list.
Thanks, I rarely use email like this so overlooked this aspect. I hope this email is better? If not let me know.
Quoted 3 lines
If you want to replace pre existing "grep" commands with "
test_grep" and pre existinggit configwithtest_config, I would recommend doing it in preparatory patches that go first in your patch series.
Yes that makes sense :)
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
In reply to Junio C HamanoQuoted 5 lines · Junio C Hamano
Hmph, in the real UI, the first letters of these commands (which have deliberately been chosen to be unique) are shown in different color to hint that the answer to the prompt can be like 's' (for status). I would hate to see that quit/help, which are somewhat special, move from the very end position.
This is the main reason I chose to put the new subcommand before as I also feel quit/help are better suited to be last, although I do see the argument against muscle memory and is valid.
Quoted 3 lines
Perhaps the example of the documentation page shown above should respond with 's', not '1' to show more prominently that it is possible and encouraged? I dunno.
Writing the first letters as opposed to the numbers is how I personally use this, just to add another perspective.
Would "config" as opposed to "settings" fix the unique lettering problem? Or perhaps config is not the best description for what it would do (I sometimes find myself using config/settings interchangeably but the majority may not...)?
Overall I feel the first two patches cover my use case the most so I am also not opposed to completely dropping the last patch about the --interactive context subcommand. Inherited diff context and command line overrides I feel are a great base to begin with either way. Just some thoughts :)
Re: [PATCH 1/3] add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetQuoted 8 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This aims to teach relevant builtins (that take in
--patch) to respect the user's diff.context and diff.interHunkContext file configurations.Since these are both UI options and
--patchis designed for the end user, I believe this was previously just an inconsistency, which this patch hopes to address.
The usual way to compose a log message of this project is to
- Give an observation on how the current system works in the present tense (so no need to say "Currently X is Y", just "X is Y"), and discuss what you perceive as a problem in it.
- Propose a solution (optional---often, problem description trivially leads to an obvious solution in reader's minds).
- Give commands to the codebase to "become like so".
in this order. "Various built-in commands that use add-patch infrastructure do not honor diff.context and diff.interHunkContext configuration variables." Would be the first sentence to explain the current situation. Follow that sentence with an explanation why it is a bad thing (i.e. it is possible that "do not honor" may be a deliberate design decision---perhaps the implementation of "add -p" is impossible if it has to honor diff.context that is set to 0; show evidence that no such deliberate design decision was there when the feature was introduced from the list archive, and say that not honoring the configuration is an inconvenient inconsistency).
Such an explanation would be sufficient for readers to guess the "solution", so stopping there should be fine.
Thanks.
Quoted 5 lines
add-interactive.c +0
-1@@ -1014,10 +1019,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; - strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
add-interactive.c static int run_diff(struct add_i_state *s, const struct pathspec *ps, · line 1028
Quoted 10 lines
add-interactive.c +7
-3-oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), - "--", NULL); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );
OK.
t/t4055-diff-context.sh test_expect_success 'diff.context honored by "log"' ' · line 58
Quoted 3 lines
t/t4055-diff-context.sh +3
-0+test_expect_success 'diff.context honored by "add"' ' + git add -p >output && + ! grep firstline output &&
test_grep ! firstline output
?
t/t4055-diff-context.sh test_expect_success 'diff.context honored by "log"' ' · line 61
Quoted 3 lines
t/t4055-diff-context.sh +3
-0+ git config diff.context 8 && + git add -p >output && + grep "^ firstline" output &&
Likewise.
test_grep "^firstline" output
?
Review
Quoted 1 line
(quoted diff) +1
-0+ git config --unset diff.context
Not like this. Either use test_when_finished to arrange that this unset is run when you leave, or use test_config.
test_expect_success title ' test_config diff.context 8 && do your tests '
will reset diff.conftext when the above piece is done.
test_expect_success title ' test_when_finished "git config unset diff.context" && git config set diff.context 8 && do your tests '
is an equivalent.
Re: [PATCH 2/3] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetHi Leon
Quoted 11 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments
8b91eef812, where builtins that accept--patchoptions now respectdiff.contextanddiff.interHunkContextfile 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.
Quoted 4 lines
This mimics
diffwhich allows for both context file configuration and command line overrides.Signed-off-by Leon Michalak <[email protected]>
I'm somewhat torn about the name "--unified" as I don't think it is particularly informative - it only makes sense if one knows the diff option and we only support a single diff format. Having said that it is probably better to reuse the name from "git diff" for consistency.
Documentation/git-add.adoc This effectively runs `add --interactive`, but bypasses the · line 116
Quoted 10 lines
+
-U<n>::
+--unified=<n>::Documentation/git-add.adoc +8
-0+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--interactive/--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--interactive/--patch`.
This documentation is repeated for each command. I think it would be better to put this in separate file that is then included where it is needed. That way if we need to update the documentation in the future we only have one copy to worry about. The syntax to include a file called diff-context-options.adoc is
include::diff-context-options.adoc[]
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 94
Quoted 11 lines
add-interactive.c +5
-0@@ -86,6 +87,11 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); + +if (add_p_opt->context !=-1 ) + s->context = add_p_opt->context; +if (add_p_opt->interhunkcontext !=-1 ) + s->interhunkcontext = add_p_opt->interhunkcontext;
This happens after we read the config so the command line option wins - good.
add-interactive.h line 6
Quoted 8 lines
index
693f125e8e4b..653f07a917b8100644add-interactive.h +1
-0@@ -3,6 +3,13 @@#include "color.h" +#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 }
I think we normally define initializer macros after the struct they initialize so the reader can more easily check the fields are all initialized correctly
add-interactive.h struct add_i_state { · line 28
Quoted 13 lines
add-interactive.h +6
-0+struct add_p_opt { +int context; +int interhunkcontext; +}; +struct add_i_state {struct repository *r;int use_color;@@ -18,14 +25,17 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext;
Should this be in the previous patch? It is a good idea to run
git rebase --keep-base --exec 'make && cd t && prove -j8
tests-that-you-think-might-fail :: --root=/dev/shm'
before submitting a patch series so that you can be sure the patches all compile and the tests pass. Running the whole test suite can be pretty slow so just run the tests that are relevant to your changes.
add-interactive.h int interactive_add(struct repository *repo, · line 174
Quoted 7 lines
add-interactive.h +2
-1@@ -169,9 +170,10 @@ int interactive_add(struct repository *repo, prefix, argv);if (patch) - ret = !!run_add_p (repo,ADD_P_ADD ,NULL , &pathspec); + ret = !!run_add_p (repo,ADD_P_ADD , add_p_opt,NULL , + &pathspec);
This line could be unwraped and still fit within 80 columns I think.
add-interactive.h static struct option builtin_add_options[] = { · line 259
Quoted 12 lines
add-interactive.h +3
-1else - ret = !!run_add_i (repo, &pathspec); + ret = !!run_add_i (repo, &pathspec, add_p_opt);clear_pathspec (&pathspec);return ret;@@ -253,6 +255,12 @@ static struct option builtin_add_options[] = {OPT_GROUP ("" ),OPT_BOOL ('i' ,"interactive" , &add_interactive,N_ ("interactive picking" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("select hunks interactively" )), + OPT_INTEGER_F('U', "unified", &add_p_opt.context, + N_("generate diffs with <n> lines context, implies --interactive/--patch"),
It cannot imply both --interactive and --patch as they are two different operations. I think it should imply --patch because that option is supported by all the commands we're adding -U to.
add-interactive.h static struct option builtin_add_options[] = { · line 263
Quoted 4 lines
add-interactive.h +4
-0+ PARSE_OPT_NONEG), +OPT_INTEGER_F (0 ,"inter-hunk-context" , &add_p_opt.interhunkcontext, +N_ ("show context between diff hunks up to the specified number of lines, implies --interactive/--patch" ), + PARSE_OPT_NONEG),
As these two options are duplicated in many commands we should define a preprocessor macro for them in parse-options.h. If you look at the end of that file there are a bunch of similar definitions.
Quoted 4 lines
add-interactive.h +0
-0OPT_BOOL ('e' ,"edit" , &edit_interactive,N_ ("edit current diff and apply" )),OPT__FORCE (&ignored_too,N_ ("allow adding otherwise ignored files" ),0 ), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
add-interactive.h int cmd_add(int argc, · line 414
Quoted 10 lines
add-interactive.h +6
-1@@ -398,7 +406,12 @@ int cmd_add(int argc,die (_ ("options '%s' and '%s' cannot be used together" ),"--dry-run" ,"--interactive/--patch" );if (pathspec_from_file)die (_ ("options '%s' and '%s' cannot be used together" ),"--pathspec-from-file" ,"--interactive/--patch" ); -exit (interactive_add (repo, argv +1 , prefix, patch_interactive)); +exit (interactive_add (repo, argv +1 , prefix, patch_interactive, &add_p_opt)); + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" );
I don't understand this - I thought the help for --unified said it implied --patch but here it is erroring out if --patch is not given.
Somewhere we should check that the values given for the context and interhunk context are non-negative. git_diff_ui_config() errors out if the context is negative and we should do the same in add-patch.c otherwise we'll get some wierd error about "git diff-index" failing. We should also think about -U0 as "git apply" rejects hunks without any context unless by default and I dont think "add -p" passes the option to enable that and I'm not sure it should.
add-interactive.h int cmd_add(int argc,
Quoted 5 lines
add-interactive.h +5
-0+test_expect_success 'The -U option overrides diff.context for "add"' ' + git config diff.context 8 && + git add -U4 -p >output && + ! grep"^ firstline" output +'
It is great that you've added tests and I do think we should test all the commands here as unlike the previous patch there isn't a common code path. My other comments about the tests in the previous patch apply here though I think.
We should have a test to check negative context values and possibly zero are rejected.
Thanks
Phillip
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
In reply to Junio C HamanoQuoted 7 lines · Junio C Hamano
An alternative that may work better is to allow subcommand specific parameters in the answer to the "What now>" prompt, e.g.
What now> r -U7
to choose an equivalent to "git revert -p -U7".
I think the best solution would be to allow users to re-display the current hunk with more context inside "add -p" rather than changing "add -i". That way a user who needs more context to make a decision on the current hunk can get it without restarting the whole process of selecting hunks [1]. If the user knows up front that they want a certain amount of context they can use "git add -p -U <context>" or "git add -i -U <context>" which was added in the preceding patch.
Best Wishes
Phillip
[1] With "git add -p" they can quit and carry on from where they left off but "git stash -p" doesn't let you amend an existing stash and git refuses to pop a stash if the working tree is dirty. This means if a stash is split in two because the user exited to change the context they cannot pop both stashes on top of each other.
Re: [PATCH 2/3] add-patch: add diff.context command line overrides
In reply to Phillip WoodQuoted 18 lines · Phillip Wood
Documentation/git-add.adoc This effectively runs `add --interactive`, but bypasses the · line 116
Quoted 11 lines
+
-U<n>::
+--unified=<n>::Documentation/git-add.adoc +8
-0+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. Implies `--interactive/--patch`. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset. Implies `--interactive/--patch`.This documentation is repeated for each command. I think it would be better to put this in separate file that is then included where it is needed. That way if we need to update the documentation in the future we only have one copy to worry about. The syntax to include a file called diff-context-options.adoc is
Quoted 1 line
include::diff-context-options.adoc[]
Excellent suggestion.
I however think "-U implies -i/-p" makes no sense at all. What if the user said "git add -U6"? Do we run "git add -i -U6" or go directly to "git add -p -U6"?
I think it is better to encourage the user to be more explicit to require them to say "git revert -U6 -p" or "git add -U6 -i".
If -U<n> is given and there is no "-i" (for "add" only) or "-p" (for everything), just error out *until* other modes of these commands find a good use of context width information, at which point we can use the context length information to drive these commands in their non-"patch" mode.
Even if we cannot think of a way to use the diff output (and with configurable context length) in modes that are not "--patch" for these commands RIGHT NOW, that does not mean -U<n> would never become useful in these modes for the commands. Let's not close the door prematurely from our future developers by making -U<n> imply anything, and make it an error to use -U<N> without -p/-i for now.
Re: [PATCH 2/3] add-patch: add diff.context command line overrides
I think I may be misunderstanding, so I'll elaborate on what I personally intended my documentation to mean.
When I put in the documentation "implies --interactive/--patch" it reads to me as "this assumes you are also using either --interactive or --patch and that if you don't specify one or the other it will do nothing or possibly error (which is what I chose in the end, based on the initial discussion in a separate thread)". I didn't think it would read as "you must have both settings" or "if you don't specify these the command will assume it as if you had and effectively act as if you had".
I'm not sure if the wording was confusing or it generally has different meanings to others so perhaps that might clarify at least what I intended :)
Re: [PATCH 3/3] add-interactive: add new "context" subcommand
In reply to Phillip WoodQuoted 6 lines · Phillip Wood
Quoted 4 lines · Junio C Hamano
An alternative that may work better is to allow subcommand specific parameters in the answer to the "What now>" prompt, e.g.
What now> r -U7
to choose an equivalent to "git revert -p -U7".
Quoted 7 lines
I think the best solution would be to allow users to re-display the current hunk with more context inside "add -p" rather than changing "add -i". That way a user who needs more context to make a decision on the current hunk can get it without restarting the whole process of selecting hunks [1]. If the user knows up front that they want a certain amount of context they can use "git add -p -U <context>" or "git add -i -U <context>" which was added in the preceding patch.
Yes, but notice that the above is about interactive mode "add -i" that is setting the diff.context to 7 for subsequent "patch" command, not against "Stage this hunk [y,n,q,...]?" prompt inside "add -p". Once you go into the "--patch" mode, especially after you let the user to edit some hunks, "redisplay this hunk with wider context" is an impossible operation with the current code structure, I think, as the implementation does not keep track of information that are needed to do so.
So, this is like "restarting 'add -p' with -U7", but done from the "add -i" session.
Re: [PATCH 2/3] add-patch: add diff.context command line overrides
In reply to Leon MichalakQuoted 12 lines · Leon Michalak
I think I may be misunderstanding, so I'll elaborate on what I personally intended my documentation to mean.
When I put in the documentation "implies --interactive/--patch" it reads to me as "this assumes you are also using either --interactive or --patch and that if you don't specify one or the other it will do nothing or possibly error (which is what I chose in the end, based on the initial discussion in a separate thread)". I didn't think it would read as "you must have both settings" or "if you don't specify these the command will assume it as if you had and effectively act as if you had".
Quoted 3 lines
I'm not sure if the wording was confusing or it generally has different meanings to others so perhaps that might clarify at least what I intended :)
We use "imply" to mean quite a different thing from what you said in the above explanation, and that is where my reaction came from.
We say "option A implies option B" only when the command behaves as if the user gave option B when only option A is given (and without giving B). For example, "git commit --help" has
--short::
When doing a dry-run, give the output in the short-format. See linkgit:git-status[1] for details. Implies --dry-run.
The --short option does not make any sense when you are actually creating a commit; if you say "git commit --short", the command behaves as if you said "git commit --dry-run --short".
If something works only under certain condition, it seems we tend to say "this only works when/with ...", so in this case, we would have said "The -U<n> option is only effective for --interactive or --patch mode of this command" to express what you meant to convey, I think.
Thanks.
v2 cover Better support for customising context lines in --patch commands
In reply to Leon Michalak via GitGitGadgetThis series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"
The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Changes since v1:
* Update commit descriptions
* Update tests to use the more modern and robust test_grep and test_config utils
* Reword some documentation / user messages
* Ensure each commit is atomic and builds/passes tests on it's own
* Make new command line options DRY
* Add tests for interhunk context interaction
* Error if context config/command line options are negative
* Drop previous last commit to do with new subcommand for --interactive add/commit. My motivations behind this patch series originally where quite simple, just for add-patch commands to respect context configs. This subcommand, after the discussion in v1, will require more thought and a larger implementation that what I had anticipated. I would prefer to leave this for another time as it's the least impactful but the most time intensive and complicated idea.
Leon Michalak (4):
test: refactor to use "test_grep"
test: refactor to use "test_config"
add-patch: respect diff.context configuration
add-patch: add diff.context command line overrides
Documentation/diff-context-options.adoc | 10 ++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 53 +++++++-- add-interactive.h | 17 ++- add-patch.c | 11 +- builtin/add.c | 16 ++- builtin/checkout.c | 24 +++- builtin/commit.c | 11 +- builtin/reset.c | 12 +- builtin/stash.c | 46 ++++++-- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 48 ++++---- t/t4032-diff-inter-hunk-context.sh | 61 ++++++++++ t/t4055-diff-context.sh | 142 ++++++++++++++++++++---- t/t9902-completion.sh | 2 + 21 files changed, 390 insertions(+), 80 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
base-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1915%2FNinjaInShade%2Finteractive-patch-context-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1915/NinjaInShade/interactive-patch-context-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1915
Range-diff vs v1:
-: ----------- > 1: 4f92a1b4c24 test: refactor to use "test_grep"
-: ----------- > 2: 75424cb8e1c test: refactor to use "test_config"
1: 8b91eef8120 ! 3: f16d3de8611 add-patch: respect diff.context configuration
@@ Metadata
## Commit message ##
add-patch: respect diff.context configuration
- This aims to teach relevant builtins (that take in `--patch`) to respect
+ Various builtins that use add-patch infrastructure do not respect
the user's diff.context and diff.interHunkContext file configurations.
-
- Since these are both UI options and `--patch` is designed for the end user,
- I believe this was previously just an inconsistency, which this patch hopes
- to address.
+ This patch fixes this inconsistency.
Signed-off-by: Leon Michalak <[email protected]>
## add-interactive.c ##
-@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repository *r)
+@@ add-interactive.c: static void init_color(struct repository *r, struct add_i_state *s,
+ void init_add_i_state(struct add_i_state *s, struct repository *r)
+ {
const char *value;
++ int context;
++ int interhunkcontext;
s->r = r;
+ s->context = -1;
@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repositor
repo_config_get_string(r, "diff.algorithm",
&s->interactive_diff_algorithm);
-+ repo_config_get_int(r, "diff.context", &s->context);
-+ repo_config_get_int(r, "diff.interHunkContext", &s->interhunkcontext);
++ if (!repo_config_get_int(r, "diff.context", &context)) {
++ if (context < 0)
++ die(_("%s cannot be negative"), "diff.context");
++ else
++ s->context = context;
++ };
++ if (!repo_config_get_int(r, "diff.interHunkContext", &interhunkcontext)) {
++ if (interhunkcontext < 0)
++ die(_("%s cannot be negative"), "diff.interHunkContext");
++ else
++ s->interhunkcontext = interhunkcontext;
++ };
+
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
if (s->use_single_key)
setbuf(stdin, NULL);
-@@ add-interactive.c: static int run_diff(struct add_i_state *s, const struct pathspec *ps,
- if (count > 0) {
- struct child_process cmd = CHILD_PROCESS_INIT;
+
+ ## add-interactive.h ##
+@@ add-interactive.h: struct add_i_state {
+
+ int use_single_key;
+ char *interactive_diff_filter, *interactive_diff_algorithm;
++ int context, interhunkcontext;
+ };
-- strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
-- oid_to_hex(!is_initial ? &oid :
-- s->r->hash_algo->empty_tree),
-- "--", NULL);
-+ strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached", NULL);
-+ if (s->context != -1)
-+ strvec_pushf(&cmd.args, "--unified=%i", s->context);
-+ if (s->interhunkcontext != -1)
-+ strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->interhunkcontext);
-+ strvec_pushl(&cmd.args, oid_to_hex(!is_initial ? &oid :
-+ s->r->hash_algo->empty_tree), "--", NULL);
- for (i = 0; i < files->items.nr; i++)
- if (files->selected[i])
- strvec_push(&cmd.args,
+ void init_add_i_state(struct add_i_state *s, struct repository *r);
## add-patch.c ##
@@ add-patch.c: static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
@@ add-patch.c: static int parse_diff(struct add_p_state *s, const struct pathspec
## t/t4055-diff-context.sh ##
@@ t/t4055-diff-context.sh: test_expect_success 'diff.context honored by "log"' '
- ! grep firstline output &&
- git config diff.context 8 &&
- git log -1 -p >output &&
-- grep "^ firstline" output
-+ grep "^ firstline" output &&
-+ git config --unset diff.context
-+'
-+
+ test_grep "^ firstline" output
+ '
+
+test_expect_success 'diff.context honored by "add"' '
+ git add -p >output &&
-+ ! grep firstline output &&
-+ git config diff.context 8 &&
-+ git add -p >output &&
-+ grep "^ firstline" output &&
-+ git config --unset diff.context
++ test_grep ! firstline output &&
++ test_config diff.context 8 &&
++ git log -1 -p >output &&
++ test_grep "^ firstline" output
+'
+
+test_expect_success 'diff.context honored by "commit"' '
+ ! git commit -p >output &&
-+ ! grep firstline output &&
-+ git config diff.context 8 &&
++ test_grep ! firstline output &&
++ test_config diff.context 8 &&
+ ! git commit -p >output &&
-+ grep "^ firstline" output &&
-+ git config --unset diff.context
++ test_grep "^ firstline" output
+'
+
+test_expect_success 'diff.context honored by "checkout"' '
+ git checkout -p >output &&
-+ ! grep firstline output &&
-+ git config diff.context 8 &&
++ test_grep ! firstline output &&
++ test_config diff.context 8 &&
+ git checkout -p >output &&
-+ grep "^ firstline" output &&
-+ git config --unset diff.context
++ test_grep "^ firstline" output
+'
+
+test_expect_success 'diff.context honored by "stash"' '
+ ! git stash -p >output &&
-+ ! grep firstline output &&
-+ git config diff.context 8 &&
++ test_grep ! firstline output &&
++ test_config diff.context 8 &&
+ ! git stash -p >output &&
-+ grep "^ firstline" output &&
-+ git config --unset diff.context
++ test_grep "^ firstline" output
+'
+
+test_expect_success 'diff.context honored by "restore"' '
+ git restore -p >output &&
-+ ! grep firstline output &&
-+ git config diff.context 8 &&
++ test_grep ! firstline output &&
++ test_config diff.context 8 &&
+ git restore -p >output &&
-+ grep "^ firstline" output &&
-+ git config --unset diff.context
++ test_grep "^ firstline" output
++'
++
+ test_expect_success 'The -U option overrides diff.context' '
+ test_config diff.context 8 &&
+ git log -U4 -1 >output &&
+@@ t/t4055-diff-context.sh: test_expect_success 'negative integer config parsing' '
+ test_grep "bad config variable" output
'
- test_expect_success 'The -U option overrides diff.context' '
++test_expect_success 'negative integer config parsing by "add"' '
++ test_config diff.context -1 &&
++ test_must_fail git add -p 2>output &&
++ test_grep "diff.context cannot be negative" output
++'
++
++test_expect_success 'negative integer config parsing by "commit"' '
++ test_config diff.context -1 &&
++ test_must_fail git commit -p 2>output &&
++ test_grep "bad config variable" output
++'
++
++test_expect_success 'negative integer config parsing by "checkout"' '
++ test_config diff.context -1 &&
++ test_must_fail git checkout -p 2>output &&
++ test_grep "diff.context cannot be negative" output
++'
++
++test_expect_success 'negative integer config parsing by "stash"' '
++ test_config diff.context -1 &&
++ test_must_fail git stash -p 2>output &&
++ test_grep "diff.context cannot be negative" output
++'
++
++test_expect_success 'negative integer config parsing by "restore"' '
++ test_config diff.context -1 &&
++ test_must_fail git restore -p 2>output &&
++ test_grep "diff.context cannot be negative" output
++'
++
+ test_expect_success '-U0 is valid, so is diff.context=0' '
+ test_config diff.context 0 &&
+ git diff >output &&
2: 7700eb173e7 ! 4: 973dfadd1b3 add-patch: add diff.context command line overrides
@@ Metadata
## Commit message ##
add-patch: add diff.context command line overrides
- This patch compliments `8b91eef812`, where builtins that accept
- `--patch` options now respect `diff.context` and `diff.interHunkContext`
- file configurations.
+ 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 `diff` which allows for both context file configuration and
- command line overrides.
+ 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]>
- ## Documentation/git-add.adoc ##
-@@ Documentation/git-add.adoc: This effectively runs `add --interactive`, but bypasses the
- initial command menu and directly jumps to the `patch` subcommand.
- See ``Interactive mode'' for details.
-
+ ## Documentation/diff-context-options.adoc (new) ##
+@@
+`-U<n>`::
+`--unified=<n>`::
+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-+ or 3 if the config option is unset. Implies `--interactive/--patch`.
++ or 3 if the config option is unset.
+
+`--inter-hunk-context=<n>`::
+ Show the context between diff hunks, up to the specified _<number>_
+ of lines, thereby fusing hunks that are close to each other.
+ Defaults to `diff.interHunkContext` or 0 if the config option
-+ is unset. Implies `--interactive/--patch`.
++ is unset.
+
+ ## Documentation/git-add.adoc ##
+@@ Documentation/git-add.adoc: This effectively runs `add --interactive`, but bypasses the
+ initial command menu and directly jumps to the `patch` subcommand.
+ See ``Interactive mode'' for details.
+
++include::diff-context-options.adoc[]
+
`-e`::
`--edit`::
@@ Documentation/git-checkout.adoc: section of linkgit:git-add[1] to learn how to o
Note that this option uses the no overlay mode by default (see also
`--overlay`), and currently doesn't support overlay mode.
-+`-U<n>`::
-+`--unified=<n>`::
-+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-+ or 3 if the config option is unset. Implies `--patch`.
-+
-+`--inter-hunk-context=<n>`::
-+ Show the context between diff hunks, up to the specified _<number>_
-+ of lines, thereby fusing hunks that are close to each other.
-+ Defaults to `diff.interHunkContext` or 0 if the config option
-+ is unset. Implies `--patch`.
++include::diff-context-options.adoc[]
+
--ignore-other-worktrees::
`git checkout` refuses when the wanted branch is already checked
@@ Documentation/git-commit.adoc: OPTIONS
which changes to commit. See linkgit:git-add[1] for
details.
-+`-U<n>`::
-+`--unified=<n>`::
-+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-+ or 3 if the config option is unset. Implies `--interactive/--patch`.
-+
-+`--inter-hunk-context=<n>`::
-+ Show the context between diff hunks, up to the specified _<number>_
-+ of lines, thereby fusing hunks that are close to each other.
-+ Defaults to `diff.interHunkContext` or 0 if the config option
-+ is unset. Implies `--interactive/--patch`.
++include::diff-context-options.adoc[]
+
`-C <commit>`::
`--reuse-message=<commit>`::
@@ Documentation/git-reset.adoc: OPTIONS
separated with _NUL_ character and all other characters are taken
literally (including newlines and quotes).
-+`-U<n>`::
-+`--unified=<n>`::
-+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-+ or 3 if the config option is unset. Implies `--patch`.
-+
-+`--inter-hunk-context=<n>`::
-+ Show the context between diff hunks, up to the specified _<number>_
-+ of lines, thereby fusing hunks that are close to each other.
-+ Defaults to `diff.interHunkContext` or 0 if the config option
-+ is unset. Implies `--patch`.
++include::diff-context-options.adoc[]
+
`--`::
Do not interpret any more arguments as options.
@@ Documentation/git-restore.adoc: leave out at most one of _<rev-A>__ and _<rev-B>
Mode" section of linkgit:git-add[1] to learn how to operate
the `--patch` mode.
-+`-U<n>`::
-+`--unified=<n>`::
-+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-+ or 3 if the config option is unset. Implies `--patch`.
-+
-+`--inter-hunk-context=<n>`::
-+ Show the context between diff hunks, up to the specified _<number>_
-+ of lines, thereby fusing hunks that are close to each other.
-+ Defaults to `diff.interHunkContext` or 0 if the config option
-+ is unset. Implies `--patch`.
++include::diff-context-options.adoc[]
+
`-W`::
`--worktree`::
@@ Documentation/git-stash.adoc: to learn how to operate the `--patch` mode.
The `--patch` option implies `--keep-index`. You can use
`--no-keep-index` to override this.
-+`-U<n>`::
-+`--unified=<n>`::
-+ Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-+ or 3 if the config option is unset. Implies `--patch`.
-+
-+`--inter-hunk-context=<n>`::
-+ Show the context between diff hunks, up to the specified _<number>_
-+ of lines, thereby fusing hunks that are close to each other.
-+ Defaults to `diff.interHunkContext` or 0 if the config option
-+ is unset. Implies `--patch`.
++include::diff-context-options.adoc[]
+
-S::
--staged::
@@ add-interactive.c: static void init_color(struct repository *r, struct add_i_sta
+ struct add_p_opt *add_p_opt)
{
const char *value;
-
+ int context;
@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repository *r)
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
if (s->use_single_key)
setbuf(stdin, NULL);
+
-+ if (add_p_opt->context != -1)
++ if (add_p_opt->context != -1) {
++ if (add_p_opt->context < 0)
++ die(_("%s cannot be negative"), "--unified");
+ s->context = add_p_opt->context;
-+ if (add_p_opt->interhunkcontext != -1)
++ }
++ if (add_p_opt->interhunkcontext != -1) {
++ if (add_p_opt->interhunkcontext < 0)
++ die(_("%s cannot be negative"), "--inter-hunk-context");
+ s->interhunkcontext = add_p_opt->interhunkcontext;
++ }
}
void clear_add_i_state(struct add_i_state *s)
@@ add-interactive.c: static int run_patch(struct add_i_state *s, const struct path
strvec_clear(&args);
clear_pathspec(&ps_selected);
}
+@@ add-interactive.c: static int run_diff(struct add_i_state *s, const struct pathspec *ps,
+ if (count > 0) {
+ struct child_process cmd = CHILD_PROCESS_INIT;
+
+- strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
+- oid_to_hex(!is_initial ? &oid :
+- s->r->hash_algo->empty_tree),
+- "--", NULL);
++ strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached", NULL);
++ if (s->context != -1)
++ strvec_pushf(&cmd.args, "--unified=%i", s->context);
++ if (s->interhunkcontext != -1)
++ strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->interhunkcontext);
++ strvec_pushl(&cmd.args, oid_to_hex(!is_initial ? &oid :
++ s->r->hash_algo->empty_tree), "--", NULL);
+ for (i = 0; i < files->items.nr; i++)
+ if (files->selected[i])
+ strvec_push(&cmd.args,
@@ add-interactive.c: static void command_prompt_help(struct add_i_state *s)
_("(empty) select nothing"));
}
@@ add-interactive.h
#include "color.h"
-+#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 }
-+
+struct add_p_opt {
+ int context;
+ int interhunkcontext;
+};
++
++#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 }
+
struct add_i_state {
struct repository *r;
int use_color;
@@ add-interactive.h: struct add_i_state {
-
- int use_single_key;
- char *interactive_diff_filter, *interactive_diff_algorithm;
-+ int context, interhunkcontext;
+ int context, interhunkcontext;
};
-void init_add_i_state(struct add_i_state *s, struct repository *r);
@@ builtin/add.c: int interactive_add(struct repository *repo,
if (patch)
- ret = !!run_add_p(repo, ADD_P_ADD, NULL, &pathspec);
-+ ret = !!run_add_p(repo, ADD_P_ADD, add_p_opt, NULL,
-+ &pathspec);
++ ret = !!run_add_p(repo, ADD_P_ADD, add_p_opt, NULL, &pathspec);
else
- ret = !!run_add_i(repo, &pathspec);
+ ret = !!run_add_i(repo, &pathspec, add_p_opt);
@@ builtin/add.c: static struct option builtin_add_options[] = {
OPT_GROUP(""),
OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
-+ OPT_INTEGER_F('U', "unified", &add_p_opt.context,
-+ N_("generate diffs with <n> lines context, implies --interactive/--patch"),
-+ PARSE_OPT_NONEG),
-+ OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
-+ N_("show context between diff hunks up to the specified number of lines, implies --interactive/--patch"),
-+ PARSE_OPT_NONEG),
++ OPT_DIFF_UNIFIED(&add_p_opt.context),
++ OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ builtin/checkout.c: static struct option *add_checkout_path_options(struct check
N_("checkout their version for unmerged files"),
3, PARSE_OPT_NONEG),
OPT_BOOL('p', "patch", &opts->patch_mode, N_("select hunks interactively")),
-+ OPT_INTEGER_F('U', "unified", &opts->patch_context,
-+ N_("generate diffs with <n> lines context, implies --patch"),
-+ PARSE_OPT_NONEG),
-+ OPT_INTEGER_F(0, "inter-hunk-context", &opts->patch_interhunk_context,
-+ N_("show context between diff hunks up to the specified number of lines, implies --patch"),
-+ PARSE_OPT_NONEG),
++ OPT_DIFF_UNIFIED(&opts->patch_context),
++ OPT_DIFF_INTERHUNK_CONTEXT(&opts->patch_interhunk_context),
OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
N_("do not limit pathspecs to sparse entries only")),
OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
@@ builtin/commit.c: int cmd_commit(int argc,
OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
-+ OPT_INTEGER_F('U', "unified", &add_p_opt.context,
-+ N_("generate diffs with <n> lines context, implies --interactive/--patch"),
-+ PARSE_OPT_NONEG),
-+ OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
-+ N_("show context between diff hunks up to the specified number of lines, implies --interactive/--patch"),
-+ PARSE_OPT_NONEG),
++ OPT_DIFF_UNIFIED(&add_p_opt.context),
++ OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
OPT_BOOL('o', "only", &only, N_("commit only specified files")),
OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit and commit-msg hooks")),
OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
@@ builtin/reset.c: int cmd_reset(int argc,
PARSE_OPT_OPTARG,
option_parse_recurse_submodules_worktree_updater),
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
-+ OPT_INTEGER_F('U', "unified", &add_p_opt.context,
-+ N_("generate diffs with <n> lines context, implies --patch"),
-+ PARSE_OPT_NONEG),
-+ OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
-+ N_("show context between diff hunks up to the specified number of lines, implies --patch"),
-+ PARSE_OPT_NONEG),
++ OPT_DIFF_UNIFIED(&add_p_opt.context),
++ OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
OPT_BOOL('N', "intent-to-add", &intent_to_add,
N_("record only the fact that removed paths will be added later")),
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
N_("stash staged changes only")),
OPT_BOOL('p', "patch", &patch_mode,
N_("stash in patch mode")),
-+ OPT_INTEGER_F('U', "unified", &add_p_opt.context,
-+ N_("generate diffs with <n> lines context, implies --patch"),
-+ PARSE_OPT_NONEG),
-+ OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
-+ N_("show context between diff hunks up to the specified number of lines, implies --patch"),
-+ PARSE_OPT_NONEG),
++ OPT_DIFF_UNIFIED(&add_p_opt.context),
++ OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
OPT__QUIET(&quiet, N_("quiet mode")),
OPT_BOOL('u', "include-untracked", &include_untracked,
N_("include untracked files in stash")),
@@ builtin/stash.c: static int save_stash(int argc, const char **argv, const char *
N_("stash staged changes only")),
OPT_BOOL('p', "patch", &patch_mode,
N_("stash in patch mode")),
-+ OPT_INTEGER_F('U', "unified", &add_p_opt.context,
-+ N_("generate diffs with <n> lines context, implies --patch"),
-+ PARSE_OPT_NONEG),
-+ OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
-+ N_("show context between diff hunks up to the specified number of lines, implies --patch"),
-+ PARSE_OPT_NONEG),
++ OPT_DIFF_UNIFIED(&add_p_opt.context),
++ OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
OPT__QUIET(&quiet, N_("quiet mode")),
OPT_BOOL('u', "include-untracked", &include_untracked,
N_("include untracked files in stash")),
@@ commit.h: int for_each_commit_graft(each_commit_graft_fn, void *);
struct commit_extra_header {
struct commit_extra_header *next;
+ ## parse-options.h ##
+@@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *, int);
+ #define OPT_PATHSPEC_FROM_FILE(v) OPT_FILENAME(0, "pathspec-from-file", v, N_("read pathspec from file"))
+ #define OPT_PATHSPEC_FILE_NUL(v) OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
+ #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
++#define OPT_DIFF_UNIFIED(v) OPT_INTEGER_F('U', "unified", v, N_("generate diffs with <n> lines context"), PARSE_OPT_NONEG)
++#define OPT_DIFF_INTERHUNK_CONTEXT(v) OPT_INTEGER_F(0, "inter-hunk-context", v, N_("show context between diff hunks up to the specified number of lines"), PARSE_OPT_NONEG)
+
+ #define OPT_IPVERSION(v) \
+ OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
+
+ ## t/t4032-diff-inter-hunk-context.sh ##
+@@ t/t4032-diff-inter-hunk-context.sh: t() {
+ "
+ }
+
++t_patch() {
++ use_config=
++ git config --unset diff.interHunkContext
++
++ case $# in
++ 4) hunks=$4; cmd="add -p -U$3";;
++ 5) hunks=$5; cmd="add -p -U$3 --inter-hunk-context=$4";;
++ 6) hunks=$5; cmd="add -p -U$3"; git config diff.interHunkContext $4; use_config="(diff.interHunkContext=$4) ";;
++ esac
++ label="$use_config$cmd, $1 common $2"
++ file=f$1
++
++ if ! test -f $file
++ then
++ f A $1 B >$file
++ git add $file
++ git commit -q -m. $file
++ f X $1 Y >$file
++ fi
++
++ test_expect_success "$label: count hunks ($hunks)" "
++ test $(test_write_lines q | git $cmd $file | sed -n 's/^([0-9]*\/\([0-9]*\)) Stage this hunk.*/\1/p') = $hunks
++ "
++}
++
+ cat <<EOF >expected.f1.0.1 || exit 1
+ diff --git a/f1 b/f1
+ --- a/f1
+@@ t/t4032-diff-inter-hunk-context.sh: t 3 lines 1 2 1 config
+ t 9 lines 3 2 2 config
+ t 9 lines 3 3 1 config
+
++# common lines ctx intrctx hunks
++t_patch 1 line 0 2
++t_patch 1 line 0 0 2
++t_patch 1 line 0 1 1
++t_patch 1 line 0 2 1
++t_patch 1 line 1 1
++
++t_patch 2 lines 0 2
++t_patch 2 lines 0 0 2
++t_patch 2 lines 0 1 2
++t_patch 2 lines 0 2 1
++t_patch 2 lines 1 1
++
++t_patch 3 lines 1 2
++t_patch 3 lines 1 0 2
++t_patch 3 lines 1 1 1
++t_patch 3 lines 1 2 1
++
++t_patch 9 lines 3 2
++t_patch 9 lines 3 2 2
++t_patch 9 lines 3 3 1
++
++# use diff.interHunkContext?
++t_patch 1 line 0 0 2 config
++t_patch 1 line 0 1 1 config
++t_patch 1 line 0 2 1 config
++t_patch 9 lines 3 3 1 config
++t_patch 2 lines 0 0 2 config
++t_patch 2 lines 0 1 2 config
++t_patch 2 lines 0 2 1 config
++t_patch 3 lines 1 0 2 config
++t_patch 3 lines 1 1 1 config
++t_patch 3 lines 1 2 1 config
++t_patch 9 lines 3 2 2 config
++t_patch 9 lines 3 3 1 config
++
+ test_expect_success 'diff.interHunkContext invalid' '
+ git config diff.interHunkContext asdf &&
+ test_must_fail git diff &&
+
## t/t4055-diff-context.sh ##
@@ t/t4055-diff-context.sh: test_expect_success 'The -U option overrides diff.context' '
- ! grep "^ firstline" output
+ test_grep ! "^ firstline" output
'
+test_expect_success 'The -U option overrides diff.context for "add"' '
-+ git config diff.context 8 &&
++ test_config diff.context 8 &&
+ git add -U4 -p >output &&
-+ ! grep "^ firstline" output
++ test_grep ! "^ firstline" output
+'
+
+test_expect_success 'The -U option overrides diff.context for "commit"' '
-+ git config diff.context 8 &&
++ test_config diff.context 8 &&
+ ! git commit -U4 -p >output &&
-+ ! grep "^ firstline" output
++ test_grep ! "^ firstline" output
+'
+
+test_expect_success 'The -U option overrides diff.context for "checkout"' '
-+ git config diff.context 8 &&
++ test_config diff.context 8 &&
+ git checkout -U4 -p >output &&
-+ ! grep "^ firstline" output
++ test_grep ! "^ firstline" output
+'
+
+test_expect_success 'The -U option overrides diff.context for "stash"' '
-+ git config diff.context 8 &&
++ test_config diff.context 8 &&
+ ! git stash -U4 -p >output &&
-+ ! grep "^ firstline" output
++ test_grep ! "^ firstline" output
+'
+
+test_expect_success 'The -U option overrides diff.context for "restore"' '
-+ git config diff.context 8 &&
++ test_config diff.context 8 &&
+ git restore -U4 -p >output &&
-+ ! grep "^ firstline" output
++ test_grep ! "^ firstline" output
+'
+
test_expect_success 'diff.context honored by "diff"' '
- git config diff.context 8 &&
+ test_config diff.context 8 &&
git diff >output &&
## t/t9902-completion.sh ## 3: b4b7854f330 < -: ----------- add-interactive: add new "context" subcommand
Signature · 1 line
gitgitgadget
PATCH v2 1/4 test: refactor to use "test_grep"
From: Leon Michalak <[email protected]>
Refactor to use the modern "test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.
This is a prerequisite to the commits that follow which add to both test files.
--- t/t3701-add-interactive.sh | 48 +++++++++++++++++++------------------- t/t4055-diff-context.sh | 28 +++++++++++----------- 2 files changed, 38 insertions(+), 38 deletions(-)
t/t3701-add-interactive.sh +24 -24
@@ -63,7 +63,7 @@ test_expect_success 'setup (initial)' ' ' test_expect_success 'status works (initial)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'setup expected' '
@@ -86,7 +86,7 @@ test_expect_success 'revert works (initial)' ' git add file && test_write_lines r 1 | git add -i && git ls-files >output && - ! grep . output + test_grep ! . output ' test_expect_success 'add untracked (multiple)' '
@@ -109,7 +109,7 @@ test_expect_success 'setup (commit)' ' ' test_expect_success 'status works (commit)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'update can stage deletions' '
@@ -141,7 +141,7 @@ test_expect_success 'revert works (commit)' ' git add file && test_write_lines r 1 | git add -i && git add -i </dev/null >output && - grep "unchanged *+3/-0 file" output + test_grep "unchanged *+3/-0 file" output ' test_expect_success 'reject multi-key input' '
@@ -185,7 +185,7 @@ test_expect_success 'setup fake editor' ' test_expect_success 'bad edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -198,7 +198,7 @@ test_expect_success 'setup patch' ' test_expect_success 'garbage edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -313,8 +313,8 @@ test_expect_success FILEMODE 'stage mode and hunk' ' chmod +x file && printf "y\\ny\\n" | git add -p && git diff --cached file >out && - grep "new mode" out && - grep "+content" out && + test_grep "new mode" out && + test_grep "+content" out && git diff file >out && test_must_be_empty out '
@@ -636,7 +636,7 @@ test_expect_success 'split hunk "add -p (edit)"' ' printf "%s\n" s e q n q q | EDITOR=: git add -p && git diff >actual && - ! grep "^+15" actual + test_grep ! "^+15" actual ' test_expect_success 'split hunk "add -p (no, yes, edit)"' '
@@ -648,7 +648,7 @@ test_expect_success 'split hunk "add -p (no, yes, edit)"' ' EDITOR=: git add -p 2>error && test_must_be_empty error && git diff >actual && - ! grep "^+31" actual + test_grep ! "^+31" actual ' test_expect_success 'split hunk with incomplete line at end' '
@@ -682,7 +682,7 @@ test_expect_success 'edit, adding lines to the first hunk' ' EDITOR=./fake_editor.sh git add -p 2>error && test_must_be_empty error && git diff --cached >actual && - grep "^+22" actual + test_grep "^+22" actual ' test_expect_success 'patch mode ignores unmerged entries' '
@@ -696,7 +696,7 @@ test_expect_success 'patch mode ignores unmerged entries' ' test_must_fail git merge side && echo changed >non-conflict.t && echo y | git add -p >output && - ! grep a/conflict.t output && + test_grep ! a/conflict.t output && cat >expected <<-\EOF && * Unmerged path conflict.t diff --git a/non-conflict.t b/non-conflict.t
@@ -728,7 +728,7 @@ test_expect_success 'diffs can be colorized' ' # We do not want to depend on the exact coloring scheme # git uses for diffs, so just check that we saw some kind of color. - grep "$(printf "\\033")" output + test_grep "$(printf "\\033")" output ' test_expect_success 'colors can be overridden' '
@@ -743,7 +743,7 @@ test_expect_success 'colors can be overridden' ' -c color.interactive.error=blue \ add -i 2>err.raw <input && test_decode_color <err.raw >err && - grep "<BLUE>Huh (trigger)?<RESET>" err && + test_grep "<BLUE>Huh (trigger)?<RESET>" err && test_write_lines help quit >input && force_color git \
@@ -863,7 +863,7 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' printf y >y && force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y && test_decode_color <output.raw >output && - grep "old<" output + test_grep "old<" output ' test_expect_success 'diffFilter filters diff' '
@@ -876,7 +876,7 @@ test_expect_success 'diffFilter filters diff' ' # avoid depending on the exact coloring or content of the prompts, # and just make sure we saw our diff prefixed - grep foo:.*content output + test_grep foo:.*content output ' test_expect_success 'detect bogus diffFilter output' '
@@ -886,7 +886,7 @@ test_expect_success 'detect bogus diffFilter output' ' test_config interactive.diffFilter "sed 6d" && printf y >y && force_color test_must_fail git add -p <y >output 2>&1 && - grep "mismatched output" output + test_grep "mismatched output" output ' test_expect_success 'handle iffy colored hunk headers' '
@@ -896,7 +896,7 @@ test_expect_success 'handle iffy colored hunk headers' ' printf n >n && force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \ add -p >output 2>&1 <n && - grep "^XX$" output + test_grep "^XX$" output ' test_expect_success 'handle very large filtered diff' '
@@ -1002,7 +1002,7 @@ test_expect_success 'add -p does not expand argument lists' ' # update it, but we want to be sure that our "." pathspec # was not expanded into the argument list of any command. # So look only for "not-changed". - ! grep -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out + test_grep ! -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out ' test_expect_success 'hunk-editing handles custom comment char' '
@@ -1072,21 +1072,21 @@ test_expect_success 'setup different kinds of dirty submodules' ' test_expect_success 'status ignores dirty submodules (except HEAD)' ' git -C for-submodules add -i </dev/null >output && - grep dirty-head output && - grep dirty-both-ways output && - ! grep dirty-otherwise output + test_grep dirty-head output && + test_grep dirty-both-ways output && + test_grep ! dirty-otherwise output ' test_expect_success 'handle submodules' ' echo 123 >>for-submodules/dirty-otherwise/initial.t && force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 && - grep "No changes" output && + test_grep "No changes" output && force_color git -C for-submodules add -p dirty-head >output 2>&1 <y && git -C for-submodules ls-files --stage dirty-head >actual && rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" && - grep "$rev" actual + test_grep "$rev" actual ' test_expect_success 'set up pathological context' '
t/t4055-diff-context.sh +14 -14
@@ -38,36 +38,36 @@ test_expect_success 'setup' ' test_expect_success 'the default number of context lines is 3' ' git diff >output && - ! grep "^ d" output && - grep "^ e" output && - grep "^ j" output && - ! grep "^ k" output + test_grep ! "^ d" output && + test_grep "^ e" output && + test_grep "^ j" output && + test_grep ! "^ k" output ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && - ! grep firstline output && + test_grep ! firstline output && git config diff.context 8 && git log -1 -p >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' git config diff.context 8 && git log -U4 -1 >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' git config diff.context 8 && git diff >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' git config diff.context 8 && git diff-files -p >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' '
@@ -85,8 +85,8 @@ test_expect_success 'negative integer config parsing' ' test_expect_success '-U0 is valid, so is diff.context=0' ' git config diff.context 0 && git diff >output && - grep "^-ADDED" output && - grep "^+MODIFIED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output ' test_expect_success '-U2147483647 works' '
@@ -94,9 +94,9 @@ test_expect_success '-U2147483647 works' ' test_line_count = 16 x && git diff -U2147483647 >output && test_line_count = 22 output && - grep "^-ADDED" output && - grep "^+MODIFIED" output && - grep "^+APPENDED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output && + test_grep "^+APPENDED" output ' test_done
Signature · 1 line
gitgitgadget
PATCH v2 2/4 test: refactor to use "test_config"
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Refactor to use the modern "test_config" test utility instead of manual "git config" as the former provides clean up on test completion.
This is a prerequisite to the commits that follow which add to this test file.
--- t/t4055-diff-context.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
t/t4055-diff-context.sh +7 -7
@@ -47,43 +47,43 @@ test_expect_success 'the default number of context lines is 3' ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && test_grep ! firstline output && - git config diff.context 8 && + test_config diff.context 8 && git log -1 -p >output && test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' - git config diff.context 8 && + test_config diff.context 8 && git log -U4 -1 >output && test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' - git config diff.context 8 && + test_config diff.context 8 && git diff >output && test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' - git config diff.context 8 && + test_config diff.context 8 && git diff-files -p >output && test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' ' - git config diff.context no && + test_config diff.context no && test_must_fail git diff 2>output && test_grep "bad numeric config value" output ' test_expect_success 'negative integer config parsing' ' - git config diff.context -1 && + test_config diff.context -1 && test_must_fail git diff 2>output && test_grep "bad config variable" output ' test_expect_success '-U0 is valid, so is diff.context=0' ' - git config diff.context 0 && + test_config diff.context 0 && git diff >output && test_grep "^-ADDED" output && test_grep "^+MODIFIED" output
Signature · 1 line
gitgitgadget
PATCH v2 3/4 add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations. This patch fixes this inconsistency.
--- add-interactive.c | 17 ++++++++++ add-interactive.h | 1 + add-patch.c | 6 ++++ t/t4055-diff-context.sh | 70 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+)
add-interactive.c +17 -0
@@ -39,8 +39,12 @@ static void init_color(struct repository *r, struct add_i_state *s,void init_add_i_state (struct add_i_state *s,struct repository *r) {const char *value; +int context; +int interhunkcontext; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;
@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &context)) { +if (context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +else + s->context = context; + }; +if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + }; +repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL );
add-interactive.h +1 -0
@@ -18,6 +18,7 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; };void init_add_i_state (struct add_i_state *s,struct repository *r);
add-patch.c +6 -0
@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) {struct strvec args =STRVEC_INIT ;const char *diff_algorithm = s->s.interactive_diff_algorithm; +int diff_context = s->s.context; +int diff_interhunkcontext = s->s.interhunkcontext;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;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)int res;strvec_pushv (&args, s->mode->diff_cmd); +if (diff_context !=-1 ) +strvec_pushf (&args,"--unified=%i" , diff_context); +if (diff_interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , diff_interhunkcontext);if (diff_algorithm)strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm);if (s->revision) {
t/t4055-diff-context.sh +70 -0
82 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH v2 4/4 add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
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.
--- Documentation/diff-context-options.adoc | 10 ++++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 36 +++++++++++---- add-interactive.h | 16 +++++-- add-patch.c | 5 +- builtin/add.c | 16 +++++-- builtin/checkout.c | 24 ++++++++-- builtin/commit.c | 11 ++++- builtin/reset.c | 12 ++++- builtin/stash.c | 46 ++++++++++++++----- commit.h | 3 +- parse-options.h | 2 + t/t4032-diff-inter-hunk-context.sh | 61 +++++++++++++++++++++++++ t/t4055-diff-context.sh | 30 ++++++++++++ t/t9902-completion.sh | 2 + 20 files changed, 251 insertions(+), 35 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
Documentation/diff-context-options.adoc new file +10 -0
@@ -0,0 +1,10 @@ +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset.
Documentation/git-add.adoc +2 -0
@@ -104,6 +104,8 @@ This effectively runs `add --interactive`, but bypasses the initial command menu and directly jumps to the `patch` subcommand. See ``Interactive mode'' for details. +include::diff-context-options.adoc[] + `-e`:: `--edit`:: Open the diff vs. the index in an editor and let the user
Documentation/git-checkout.adoc +2 -0
@@ -289,6 +289,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. +include::diff-context-options.adoc[] + --ignore-other-worktrees:: `git checkout` refuses when the wanted branch is already checked out or otherwise in use by another worktree. This option makes
Documentation/git-commit.adoc +2 -0
@@ -76,6 +76,8 @@ OPTIONS which changes to commit. See linkgit:git-add[1] for details. +include::diff-context-options.adoc[] + `-C <commit>`:: `--reuse-message=<commit>`:: Take an existing _<commit>_ object, and reuse the log message
Documentation/git-reset.adoc +2 -0
@@ -125,6 +125,8 @@ OPTIONS separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). +include::diff-context-options.adoc[] + `--`:: Do not interpret any more arguments as options.
Documentation/git-restore.adoc +2 -0
@@ -52,6 +52,8 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. +include::diff-context-options.adoc[] + `-W`:: `--worktree`:: `-S`::
Documentation/git-stash.adoc +2 -0
@@ -208,6 +208,8 @@ to learn how to operate the `--patch` mode. The `--patch` option implies `--keep-index`. You can use `--no-keep-index` to override this. +include::diff-context-options.adoc[] + -S:: --staged:: This option is only valid for `push` and `save` commands.
add-interactive.c +28 -8
@@ -36,7 +36,8 @@ static void init_color(struct repository *r, struct add_i_state *s,free (key); } -void init_add_i_state (struct add_i_state *s,struct repository *r) +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt) {const char *value;int context;
@@ -98,6 +99,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); + +if (add_p_opt->context !=-1 ) { +if (add_p_opt->context <0 ) +die (_ ("%s cannot be negative" ),"--unified" ); + s->context = add_p_opt->context; + } +if (add_p_opt->interhunkcontext !=-1 ) { +if (add_p_opt->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"--inter-hunk-context" ); + s->interhunkcontext = add_p_opt->interhunkcontext; + } }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, opts->prompt =N_ ("Patch update" ); count =list_and_choose (s, files, opts);if (count >0 ) { +struct add_p_opt add_p_opt = { + .context = s->context, + .interhunkcontext = s->interhunkcontext, + };struct strvec args =STRVEC_INIT ;struct pathspec ps_selected = {0 };
@@ -996,7 +1012,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,parse_pathspec (&ps_selected,PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL ,PATHSPEC_LITERAL_PATH ,"" , args.v); - res =run_add_p (s->r,ADD_P_ADD ,NULL , &ps_selected); + res =run_add_p (s->r,ADD_P_ADD , &add_p_opt,NULL , &ps_selected);strvec_clear (&args);clear_pathspec (&ps_selected); }
@@ -1031,10 +1047,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; -strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" , -oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), -"--" ,NULL ); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );for (i =0 ; i < files->items.nr; i++)if (files->selected[i]) strvec_push(&cmd.args,
@@ -1127,7 +1146,8 @@ static void command_prompt_help(struct add_i_state *s) _("(empty) select nothing")); } -int run_add_i (struct repository *r,const struct pathspec *ps) +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt) {struct add_i_state s = {NULL };struct print_command_item_data data = {"[" ,"]" };
@@ -1170,7 +1190,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps) ->util = util; } -init_add_i_state (&s, r); +init_add_i_state (&s, r, add_p_opt);/* * When color was asked for, use the prompt color for
add-interactive.h +13 -3
@@ -3,6 +3,13 @@#include "color.h" +struct add_p_opt { +int context; +int interhunkcontext; +}; + +#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 } +struct add_i_state {struct repository *r;int use_color;
@@ -21,12 +28,14 @@ struct add_i_state {int context, interhunkcontext; }; -void init_add_i_state (struct add_i_state *s,struct repository *r); +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt);void clear_add_i_state (struct add_i_state *s);struct repository ;struct pathspec ; -int run_add_i (struct repository *r,const struct pathspec *ps); +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt);enum add_p_mode {ADD_P_ADD ,
@@ -37,6 +46,7 @@ enum add_p_mode { };int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps); +struct add_p_opt *o,const char *revision, +const struct pathspec *ps);#endif
add-patch.c +3 -2
@@ -1766,14 +1766,15 @@ soft_increment: }int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps) +struct add_p_opt *o,const char *revision, +const struct pathspec *ps) {struct add_p_state s = { { r },STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT };size_t i, binary_count =0 ; -init_add_i_state (&s.s, r); +init_add_i_state (&s.s, r, o);if (mode ==ADD_P_STASH ) s.mode = &patch_mode_stash;
builtin/add.c +12 -4
@@ -29,6 +29,7 @@ static const char * const builtin_add_usage[] = { NULL };static int patch_interactive, add_interactive, edit_interactive; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int take_worktree_changes;static int add_renormalize;static int pathspec_file_nul;
@@ -157,7 +158,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch) +int patch,struct add_p_opt *add_p_opt) {struct pathspec pathspec;int ret;
@@ -169,9 +170,9 @@ int interactive_add(struct repository *repo, prefix, argv);if (patch) - ret = !!run_add_p (repo,ADD_P_ADD ,NULL , &pathspec); + ret = !!run_add_p (repo,ADD_P_ADD , add_p_opt,NULL , &pathspec);else - ret = !!run_add_i (repo, &pathspec); + ret = !!run_add_i (repo, &pathspec, add_p_opt);clear_pathspec (&pathspec);return ret;
@@ -253,6 +254,8 @@ static struct option builtin_add_options[] = {OPT_GROUP ("" ),OPT_BOOL ('i' ,"interactive" , &add_interactive,N_ ("interactive picking" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('e' ,"edit" , &edit_interactive,N_ ("edit current diff and apply" )),OPT__FORCE (&ignored_too,N_ ("allow adding otherwise ignored files" ),0 ), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -398,7 +401,12 @@ int cmd_add(int argc,die (_ ("options '%s' and '%s' cannot be used together" ),"--dry-run" ,"--interactive/--patch" );if (pathspec_from_file)die (_ ("options '%s' and '%s' cannot be used together" ),"--pathspec-from-file" ,"--interactive/--patch" ); -exit (interactive_add (repo, argv +1 , prefix, patch_interactive)); +exit (interactive_add (repo, argv +1 , prefix, patch_interactive, &add_p_opt)); + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }if (edit_interactive) {
builtin/checkout.c +21 -3
@@ -61,6 +61,8 @@ static const char * const restore_usage[] = {struct checkout_opts {int patch_mode; +int patch_context; +int patch_interhunk_context;int quiet;int merge;int force;
@@ -104,7 +106,12 @@ struct checkout_opts {struct tree *source_tree; }; -#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 } +#define CHECKOUT_OPTS_INIT { \ + .conflict_style = -1, \ + .merge = -1, \ + .patch_context = -1, \ + .patch_interhunk_context = -1, \ +}struct branch_info {char *name;/* The short name used */
@@ -539,6 +546,10 @@ static int checkout_paths(const struct checkout_opts *opts,if (opts->patch_mode) {enum add_p_mode patch_mode; +struct add_p_opt add_p_opt = { + .context = opts->patch_context, + .interhunkcontext = opts->patch_interhunk_context, + };const char *rev = new_branch_info->name;char rev_oid[GIT_MAX_HEXSZ +1 ];
@@ -564,8 +575,13 @@ static int checkout_paths(const struct checkout_opts *opts,else BUG ("either flag must have been set, worktree=%d, index=%d" , opts->checkout_worktree, opts->checkout_index); -return !!run_add_p (the_repository, patch_mode, rev, - &opts->pathspec); +return !!run_add_p (the_repository, patch_mode, &add_p_opt, + rev, &opts->pathspec); + }else { +if (opts->patch_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (opts->patch_interhunk_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }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, N_("checkout their version for unmerged files"), 3, PARSE_OPT_NONEG),OPT_BOOL ('p' ,"patch" , &opts->patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&opts->patch_context), +OPT_DIFF_INTERHUNK_CONTEXT (&opts->patch_interhunk_context),OPT_BOOL (0 ,"ignore-skip-worktree-bits" , &opts->ignore_skipworktree,N_ ("do not limit pathspecs to sparse entries only" )), OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
builtin/commit.c +10 -1
@@ -19,6 +19,7 @@#include "environment.h" #include "diff.h" #include "commit.h" +#include "add-interactive.h" #include "gettext.h" #include "revision.h" #include "wt-status.h"
@@ -122,6 +123,7 @@ static const char *edit_message, *use_message;static char *fixup_message, *fixup_commit, *squash_message;static const char *fixup_prefix;static int all, also, interactive, patch_interactive, only, amend, signoff; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int edit_flag =-1 ;/* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */
@@ -400,7 +402,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env =xstrdup_or_null (getenv (INDEX_ENVIRONMENT ));setenv (INDEX_ENVIRONMENT , the_repository->index_file,1 ); -if (interactive_add (the_repository, argv, prefix, patch_interactive) !=0 ) +if (interactive_add (the_repository, argv, prefix, patch_interactive, &add_p_opt) !=0 )die (_ ("interactive add failed" )); the_repository->index_file = old_repo_index_file;
@@ -424,6 +426,11 @@ static const char *prepare_index(const char **argv, const char *prefix, commit_style =COMMIT_NORMAL ; ret =get_lock_file_path (&index_lock); goto out; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }/*
@@ -1722,6 +1729,8 @@ int cmd_commit(int argc,OPT_BOOL ('i' ,"include" , &also,N_ ("add specified files to index for commit" )),OPT_BOOL (0 ,"interactive" , &interactive,N_ ("interactively add files" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("interactively add changes" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('o' ,"only" , &only,N_ ("commit only specified files" )),OPT_BOOL ('n' ,"no-verify" , &no_verify,N_ ("bypass pre-commit and commit-msg hooks" )), OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
builtin/reset.c +10 -2
@@ -346,6 +346,7 @@ int cmd_reset(int argc,struct object_id oid;struct pathspec pathspec;int intent_to_add =0 ; +struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;const struct option options[] = {OPT__QUIET (&quiet,N_ ("be quiet, only report errors" )), OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -370,6 +371,8 @@ int cmd_reset(int argc, PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),OPT_BOOL ('p' ,"patch" , &patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('N' ,"intent-to-add" , &intent_to_add,N_ ("record only the fact that removed paths will be added later" )), OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -424,9 +427,14 @@ int cmd_reset(int argc,if (reset_type !=NONE )die (_ ("options '%s' and '%s' cannot be used together" ),"--patch" ,"--{hard,mixed,soft}" );trace2_cmd_mode ("patch-interactive" ); - update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , rev, - &pathspec); + update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , + &add_p_opt, rev, &pathspec); goto cleanup; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }/* git reset tree [--] paths... can be used to
builtin/stash.c +35 -11
126 lines not on this page · raw message
commit.h +2 -1
@@ -2,6 +2,7 @@#define COMMIT_H #include "object.h" +#include "add-interactive.h" struct signature_check ;struct strbuf ;
@@ -257,7 +258,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch); +int patch,struct add_p_opt *add_p_opt);struct commit_extra_header {struct commit_extra_header *next;
parse-options.h +2 -0
@@ -616,6 +616,8 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);#define OPT_PATHSPEC_FROM_FILE (v) OPT_FILENAME(0, "pathspec-from-file", v, N_("read pathspec from file"))#define OPT_PATHSPEC_FILE_NUL (v) OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))#define OPT_AUTOSTASH (v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after")) +#define OPT_DIFF_UNIFIED (v) OPT_INTEGER_F('U', "unified", v, N_("generate diffs with <n> lines context"), PARSE_OPT_NONEG) +#define OPT_DIFF_INTERHUNK_CONTEXT (v) OPT_INTEGER_F(0, "inter-hunk-context", v, N_("show context between diff hunks up to the specified number of lines"), PARSE_OPT_NONEG)#define OPT_IPVERSION (v) \ OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
t/t4032-diff-inter-hunk-context.sh +61 -0
73 lines not on this page · raw message
t/t4055-diff-context.sh +30 -0
@@ -98,6 +98,36 @@ test_expect_success 'The -U option overrides diff.context' ' test_grep ! "^ firstline" output ' +test_expect_success 'The -U option overrides diff.context for "add"' ' + test_config diff.context 8 && + git add -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "commit"' ' + test_config diff.context 8 && + ! git commit -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "checkout"' ' + test_config diff.context 8 && + git checkout -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "stash"' ' + test_config diff.context 8 && + ! git stash -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "restore"' ' + test_config diff.context 8 && + git restore -U4 -p >output && + test_grep ! "^ firstline" output +' + test_expect_success 'diff.context honored by "diff"' ' test_config diff.context 8 && git diff >output &&
t/t9902-completion.sh +2 -0
@@ -2596,6 +2596,8 @@ test_expect_success 'double dash "git checkout"' ' --merge Z --conflict=Z --patch Z + --unified=Z + --inter-hunk-context=Z --ignore-skip-worktree-bits Z --ignore-other-worktrees Z --recurse-submodules Z
Signature · 1 line
gitgitgadget
Re: [PATCH v2 1/4] test: refactor to use "test_grep"
In reply to Leon Michalak via GitGitGadgetQuoted 10 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Refactor to use the modern "
test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.This is a prerequisite to the commits that follow which add to both test files.
Signed-off-by Leon Michalak <[email protected]>---
These mostly look sensible, but I would title & phrase the commit description to 'use "test_grep"', not 'refactor to &'. It's shorter and more direct ;-)
Thanks.
Re: [PATCH v2 4/4] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetQuoted 6 lines · Leon Michalak via GitGitGadget
Documentation/diff-context-options.adoc new file +0
-0
Documentation/diff-context-options.adoc line 10
Quoted 10 lines
Documentation/diff-context-options.adoc new file +10
-0@@ -0,0 +1,10 @@ +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset.
It might not be trivial to do but I wonder if we cannot do better than this to share more of the same text across manual pages. These two being options understood by git diff, we certainly have an existing description for them, no?
Other than that, looking good to me.
Thanks.
Re: [PATCH v2 1/4] test: refactor to use "test_grep"
In reply to Junio C HamanoQuoted 3 lines · Junio C Hamano
These mostly look sensible, but I would title & phrase the commit description to 'use "
test_grep"', not 'refactor to &'. It's shorter and more direct ;-)
Thanks - will make sure to change that in v3 :)
Re: [PATCH v2 4/4] add-patch: add diff.context command line overrides
In reply to Junio C HamanoQuoted 4 lines · Junio C Hamano
It might not be trivial to do but I wonder if we cannot do better than this to share more of the same text across manual pages. These two being options understood by
git diff, we certainly have an existing description for them, no?
Yes, I did of course notice documentation for git diff also has these; ultimately my justification for not changing that to use this new .adoc include as well was for a couple reasons:
- these two options are not together in the git diff documentation (not *so* important, and they probably should actually be together?)
- there is an extra if def which adds on "implies --patch" text in the git diff documentation which isn't the behaviour the add-patch commands are going for, so that makes the intent a little different here
But would be good to hear if anyone else has any thoughts.
Re: [PATCH v2 3/4] add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetHi Leon
Quoted 4 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations.
We could expand this slightly by adding
This is because the plumbing commands used by "git add -p" to generate the diff do not read those config settings. Fix this by reading the config before generating the patch and passing it along to the diff command with the "-U" and "--inter-hunk-context" command-line options.
Quoted 11 lines
This patch fixes this inconsistency.
Signed-off-by Leon Michalak <[email protected]>---
add-interactive.c +2
-0@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &context)) { +if (context <0 )
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 96
Quoted 10 lines
add-interactive.c +10
-0+die (_ ("%s cannot be negative" ),"diff.context" ); + else + s->context = context; + }; +if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + };
Thanks for changing this. This iteration of the code changes looks good
t/t4055-diff-context.sh test_expect_success 'diff.context honored by "log"' ' · line 53
Quoted 7 lines
t/t4055-diff-context.sh +0
-0@@ -52,6 +52,46 @@ test_expect_success 'diff.context honored by "log"' ' test_grep "^ firstline" output '
It's great that you have written tests for this patch but as I said last time I think the new tests should be in t3701-add-interactive.sh as we're interested in testing whether "git add -p" passes on diff.context to "git diff" , not whether "git diff" respects diff.context. I still think there are too many tests here as we know that all the different "-p" commands share a single code path. Our test suite is slow enough already so we do not want to add new tests that do not increase our code coverage. I would suggest removing these tests and instead add the following in t3701
test_expect_success 'add -p respects diff.context' '
test_write_lines a b c d e f g h i j k l m >file && git add file && test_write_lines a b c d e f G h i j k l m >file && echo y | git -c diff.context=5 add -p >actual && test_grep "@@ -2,11 +2,11 @@" actual
'
test_expect_success 'add -p respects diff.interHunkContext' '
test_write_lines a b c d e f g h i j k l m n o p q r s >file && git add file && test_write_lines a b c d E f g i i j k l m N o p q r s >file && echo y | git -c diff.interhunkcontext=2 add -p >actual && test_grep "@@ -2,16 +2,16 @@" actual
'
t/t4055-diff-context.sh test_expect_success 'negative integer config parsing' ' · line 125
Quoted 1 line
t/t4055-diff-context.sh +1
-0+test_expect_success 'negative integer config parsing by "add"' '
Perhaps "add -p rejects negative diff.context" would be clearer?
t/t4055-diff-context.sh test_expect_success 'negative integer config parsing' ' · line 129
Quoted 4 lines
t/t4055-diff-context.sh +4
-0+ test_config diff.context -1 && + test_must_fail git add -p 2>output && + test_grep "diff.context cannot be negative" output +'
This is great but again we only need to test a single command and we should do so in t3701. We should also check that negative values of diff.interHunkContext are also rejected.
Best Wishes
Phillip
Re: [PATCH v2 4/4] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetHi Leon
Quoted 6 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments the previous commit, where builtins that use add-patch infrastructure now respect diff.context and diff.interHunkContext file configurations.
Quoted 7 lines
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.
The code changes here mostly look good, I've left a few comments below. I think the tests could be improved, I've left some suggestions on limiting the number of tests while improving the coverage. The new tests I'm suggesting that check invalid option combinations are the basis for most of my code comments.
There is still the issue of what to do with -U0. As I mentioned previously "git apply" will fail when we try to apply the patch. We can either pass the appropriate flag when the context is zero or possibly use -U0 to mean the default number of context lines.
Quoted 6 lines
Documentation/diff-context-options.adoc new file +0
-0
Documentation/diff-context-options.adoc line 10
Quoted 10 lines
Documentation/diff-context-options.adoc new file +10
-0@@ -0,0 +1,10 @@ +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset.
Nice - we reuse the same text for all the "-p" commands.
Quoted 7 lines
add-interactive.c +1
-0@@ -98,6 +99,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); +
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 112
Quoted 10 lines
add-interactive.c +10
-0+if (add_p_opt->context !=-1 ) { +if (add_p_opt->context <0 ) +die (_ ("%s cannot be negative" ),"--unified" ); + s->context = add_p_opt->context; + } +if (add_p_opt->interhunkcontext !=-1 ) { +if (add_p_opt->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"--inter-hunk-context" ); + s->interhunkcontext = add_p_opt->interhunkcontext; + }
Centralizing these checks like this is a good idea.
Quoted 5 lines
add-interactive.c +0
-1@@ -1031,10 +1047,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; - strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
add-interactive.c static int run_diff(struct add_i_state *s, const struct pathspec *ps, · line 1056
Quoted 10 lines
add-interactive.c +7
-3-oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), - "--", NULL); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );
This is good - we propagate the values we were given on the command-line.
Quoted 6 lines
builtin/checkout.c +0
-0@@ -564,8 +575,13 @@ static int checkout_paths(const struct checkout_opts *opts,else BUG ("either flag must have been set, worktree=%d, index=%d" , opts->checkout_worktree, opts->checkout_index);
builtin/checkout.c static int checkout_paths(const struct checkout_opts *opts, · line 585
Quoted 10 lines
builtin/checkout.c +7
-2-return !!run_add_p (the_repository, patch_mode, rev, - &opts->pathspec); +return !!run_add_p (the_repository, patch_mode, &add_p_opt, + rev, &opts->pathspec); + }else { +if (opts->patch_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (opts->patch_interhunk_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }
This does not catch "git checkout -U 7" because this code is only run if we're checking out paths. I think you need to check this is checkout_main() instead.
builtin/stash.c static int push_stash(int argc, const char **argv, const char *prefix, · line 1840
Quoted 13 lines
builtin/stash.c +7
-0@@ -1826,8 +1831,15 @@ static int push_stash(int argc, const char **argv, const char *prefix,die (_ ("the option '%s' requires '%s'" ),"--pathspec-file-nul" ,"--pathspec-from-file" ); } +if (!patch_mode) { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); + } +
This needs to die on invalid context values as "git stash" seems to ignore the exit code of the subprocess that checks for negative values.
builtin/stash.c static int save_stash(int argc, const char **argv, const char *prefix, · line 1900
Quoted 10 lines
builtin/stash.c +6
-0@@ -1877,8 +1892,17 @@ static int save_stash(int argc, const char **argv, const char *prefix, stash_msg =strbuf_join_argv (&stash_msg_buf, argc, argv,' ' );memset (&ps,0 ,sizeof (ps)); + +if (!patch_mode) { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" );
This needs to die on invalid context values as "git stash" seems to ignore the exit code of the subprocess that checks for negative values.
commit.h line 8
Quoted 6 lines
commit.h +1
-0#include "object.h" +#include "add-interactive.h" struct signature_check ;struct strbuf ;
Lets not add this. Instead lets just add a declaration for "struct add_p_opt" like the ones in the context line so that we don't end up including everything from add-interactive.h when we only need a single struct declaration.
parse-options.h
Quoted 4 lines
parse-options.h +1
-0+#define OPT_DIFF_UNIFIED (v) OPT_INTEGER_F('U', "unified", v, N_("generate diffs with <n> lines context"), PARSE_OPT_NONEG)
This looks good
Quoted 1 line
+#define
OPT_DIFF_INTERHUNK_CONTEXT(v)OPT_INTEGER_F(0, "inter-hunk-context", v,N_("show context between diff hunks up to the specified number of lines"),PARSE_OPT_NONEG)
This is a bit verbose but it matches what is in diff.c.
Quoted 66 lines
t/t4032-diff-inter-hunk-context.sh +51
-0@@ -47,6 +47,31 @@ t() { " } +t_patch() { + use_config= + git config --unset diff.interHunkContext + + case $# in + 4) hunks=$4; cmd="add -p -U$3";; + 5) hunks=$5; cmd="add -p -U$3 --inter-hunk-context=$4";; + 6) hunks=$5; cmd="add -p -U$3"; git config diff.interHunkContext $4; use_config="(diff.interHunkContext=$4) ";; + esac + label="$use_config$cmd, $1 common $2" + file=f$1 + + if ! test -f $file + then + f A $1 B >$file + git add $file + git commit -q -m. $file + f X $1 Y >$file + fi + + test_expect_success "$label: count hunks ($hunks)" " + test $(test_write_lines q | git $cmd $file | sed -n 's/^([0-9]*\/\([0-9]*\)) Stage this hunk.*/\1/p') = $hunks + " +} + cat <<EOF >expected.f1.0.1 || exit 1 diff --git a/f1 b/f1 --- a/f1@@ -107,6 +132,42 @@ t 3 lines 1 2 1 config t 9 lines 3 2 2 config t 9 lines 3 3 1 config +# common lines ctx intrctx hunks +t_patch 1 line 0 2 +t_patch 1 line 0 0 2 +t_patch 1 line 0 1 1 +t_patch 1 line 0 2 1 +t_patch 1 line 1 1 + +t_patch 2 lines 0 2 +t_patch 2 lines 0 0 2 +t_patch 2 lines 0 1 2 +t_patch 2 lines 0 2 1 +t_patch 2 lines 1 1 + +t_patch 3 lines 1 2 +t_patch 3 lines 1 0 2 +t_patch 3 lines 1 1 1 +t_patch 3 lines 1 2 1 + +t_patch 9 lines 3 2 +t_patch 9 lines 3 2 2 +t_patch 9 lines 3 3 1 + +# use diff.interHunkContext? +t_patch 1 line 0 0 2 config +t_patch 1 line 0 1 1 config +t_patch 1 line 0 2 1 config
t/t4032-diff-inter-hunk-context.sh t 3 lines 1 2 1 config · line 170
Quoted 10 lines
t/t4032-diff-inter-hunk-context.sh +10
-0+t_patch 9 lines 3 3 1 config +t_patch 2 lines 0 0 2 config +t_patch 2 lines 0 1 2 config +t_patch 2 lines 0 2 1 config +t_patch 3 lines 1 0 2 config +t_patch 3 lines 1 1 1 config +t_patch 3 lines 1 2 1 config +t_patch 9 lines 3 2 2 config +t_patch 9 lines 3 3 1 config +
There are 29 tests here and yet more below. I think we can get the test coverage we need much more efficiently with the following added to t3701
for cmd in add checkout restore 'commit -m file'
do
test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" "
test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
git add file &&
test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
$cmd -p -U 4 --inter-hunk-context 2 >actual &&
test_grep \"@@ -2,20 +2,20 @@\" actual
"done
test_expect_success 'reset accepts -U and --inter-hunk-context' '
test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && git commit -m file file && test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && git add file && echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ reset -p -U 4 --inter-hunk-context 2 >actual && test_grep "@@ -2,20 +2,20 @@" actual
'
test_expect_success 'stash accepts -U and --inter-hunk-context' '
test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && git commit -m file file && test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ stash -p -U 4 --inter-hunk-context 2 >actual && test_grep "@@ -2,20 +2,20 @@" actual
'
Those tests will fail if any of the commands that accept "-p" do not accept "-U" or "--inter-hunk-context" or if command-line arguments do not override the config settings. We should also add tests in t3701 to check that invalid option combinations and values are rejected like so
for cmd in add checkout commit reset restore 'stash save' 'stash push' do
test_expect_success "$cmd rejects invalid context options" " test_must_fail git $cmd -p -U -3 2>actual && test_grep -e \"--unified cannot be negative\" actual && test_must_fail git $cmd -p --inter-hunk-context -3 2>actual && test_grep -e \"--inter-hunk-context cannot be negative\" actual && test_must_fail git $cmd -U 7 2>actual && test_grep -E \".--unified. requires .(--interactive/)?--patch.\" actual && test_must_fail git $cmd --inter-hunk-context 2 2>actual && test_grep -E \".--inter-hunk-context. requires .(--interactive/)?--patch.\" actual "
done
The "checkout", "stash save" and "stash push" tests above currently fail because the implementation does not implement those checks properly.
With a few tweaks this series will be looking very good
Best Wishes
Phillip
Re: [PATCH v2 4/4] add-patch: add diff.context command line overrides
Quoted 10 lines · Phillip Wood
Quoted 10 lines
builtin/stash.c +3
-0@@ -1826,8 +1831,15 @@ static int push_stash(int argc, const char **argv, const char *prefix, die(_("the option '%s' requires '%s'"), "--pathspec-file- nul", "--pathspec-from-file"); } + if (!patch_mode) { + if (add_p_opt.context != -1) + die(_("the option '%s' requires '%s'"), "--unified", "-- patch");
Quoted 8 lines
builtin/stash.c static int push_stash(int argc, const char **argv, const char *prefix, · line 1840
Quoted 5 lines
builtin/stash.c +4
-0+ if (add_p_opt.interhunkcontext != -1) + die(_("the option '%s' requires '%s'"), "--inter-hunk- context", "--patch"); + } +This needs to die on invalid context values as "git stash" seems to ignore the exit code of the subprocess that checks for negative values.
Looking more closely the problem is that it quits if there are no changes to stash before validating -U or --inter-hunk-context. I think it should validate the options before checking if there is anything to stash.
Best Wishes
Phillip
Re: [PATCH v2 4/4] add-patch: add diff.context command line overrides
Hey, thanks for the thorough review Philip. I will properly digest this when I get some free time, but I just wanted to say (I probably should have mentioned this so my bad) that the reason I didn't change to test just the singular command (yet, anyway) is that someone else thought this was a good idea testing all of them, so I wasn't sure whether to touch it or not in the end, and thought I'd just submit this v2 and gather more opinions. Was this perhaps the wrong approach though?
Re: [PATCH v2 3/4] add-patch: respect diff.context configuration
In reply to Phillip WoodQuoted 27 lines · Phillip Wood
Hi Leon
Quoted 3 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations.We could expand this slightly by adding
This is because the plumbing commands used by "git add -p" to generate the diff do not read those config settings. Fix this by reading the config before generating the patch and passing it along to the diff command with the "-U" and "--inter-hunk-context" command-line options.
Quoted 13 lines
This patch fixes this inconsistency.
Signed-off-by Leon Michalak <[email protected]>---
add-interactive.c +5
-0@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); + if (!repo_config_get_int(r, "diff.context", &context)) { +if (context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +else + s->context = context; + };
Quoted 8 lines
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 96
Quoted 6 lines
add-interactive.c +6
-0+if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + };Thanks for changing this. This iteration of the code changes looks good
Lose the ';' (semicolon) after closing {brace}s. This is C; you do not need an empty statement after a {block}.
Everything in your review I am very happy to see. Thanks for giving a great review.
Re: [PATCH v2 4/4] add-patch: add diff.context command line overrides
In reply to Leon MichalakHi Leon
Quoted 5 lines · Leon Michalak
Hey, thanks for the thorough review Philip. I will properly digest this when I get some free time, but I just wanted to say (I probably should have mentioned this so my bad) that the reason I didn't change to test just the singular command (yet, anyway) is that someone else thought this was a good idea testing all of them,
I'd missed that message - have you got a link to it please
Quoted 4 lines
so I wasn't sure
whether to touch it or not in the end, and thought I'd just submit this v2 and gather more opinions. Was this perhaps the wrong approach though?
If you get conflicting advise then it is a good idea to mention that in the cover letter and explain which option you went with and why.
Best Wishes
Phillip
Re: [PATCH v2 3/4] add-patch: respect diff.context configuration
In reply to Junio C HamanoQuoted 21 lines · Junio C Hamano
Quoted 11 lines · Phillip Wood
Quoted 9 lines · Leon Michalak via GitGitGadget
add-interactive.c +5
-0@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); + if (!repo_config_get_int(r, "diff.context", &context)) { +if (context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +else + s->context = context; + };Quoted 8 lines
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 96
Quoted 6 lines
add-interactive.c +6
-0+if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + };Thanks for changing this. This iteration of the code changes looks good
Quoted 2 lines
Lose the ';' (semicolon) after closing {brace}s. This is C; you do not need an empty statement after a {block}.
Oh well spotted, I'd missed that
Thanks
Phillip
Re: [PATCH v2 3/4] add-patch: respect diff.context configuration
Quoted 21 lines · Phillip Wood
Quoted 20 lines · Junio C Hamano
Quoted 19 lines · Phillip Wood
Quoted 5 lines · Leon Michalak via GitGitGadget
add-interactive.c +1
-0@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); + if (!repo_config_get_int(r, "diff.context", &context)) { +if (context <0 )add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 95
Quoted 10 lines
add-interactive.c +10
-0+die (_ ("%s cannot be negative" ),"diff.context" ); + else + s->context = context; + }; +if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + };Thanks for changing this. This iteration of the code changes looks good
Quoted 4 lines
Quoted 2 lines
Lose the ';' (semicolon) after closing {brace}s. This is C; you do not need an empty statement after a {block}.
Oh well spotted, I'd missed that
Heh, with enough number of eyeballs, all the bugs are shallow.
v3 cover Better support for customising context lines in --patch commands
In reply to Leon Michalak via GitGitGadgetThis series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"
The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Changes since v1:
* Update commit descriptions
* Update tests to use the more modern and robust test_grep and test_config utils
* Reword some documentation / user messages
* Ensure each commit is atomic and builds/passes tests on it's own
* Make new command line options DRY
* Add tests for interhunk context interaction
* Error if context config/command line options are negative
* Drop previous last commit to do with new subcommand for --interactive add/commit. My motivations behind this patch series originally where quite simple, just for add-patch commands to respect context configs. This subcommand, after the discussion in v1, will require more thought and a larger implementation that what I had anticipated. I would prefer to leave this for another time as it's the least impactful but the most time intensive and complicated idea.
Changes since v2:
* Update tests to only test single command (following Philip's suggestion)
* Add negative option checks
* Minor commit re-wording
Leon Michalak (4):
test: use "test_grep"
test: use "test_config"
add-patch: respect diff.context configuration
add-patch: add diff.context command line overrides
Documentation/diff-context-options.adoc | 10 ++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 53 +++++++++-- add-interactive.h | 17 +++- add-patch.c | 11 ++- builtin/add.c | 21 ++++- builtin/checkout.c | 31 +++++- builtin/commit.c | 16 +++- builtin/reset.c | 17 +++- builtin/stash.c | 56 ++++++++--- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 119 +++++++++++++++++++----- t/t4055-diff-context.sh | 72 +++++++++----- t/t9902-completion.sh | 2 + 20 files changed, 362 insertions(+), 80 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
base-commit: cf6f63ea6bf35173e02e18bdc6a4ba41288acff9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1915%2FNinjaInShade%2Finteractive-patch-context-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1915/NinjaInShade/interactive-patch-context-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1915
Range-diff vs v2:
1: 4f92a1b4c24 ! 1: 044a93014b6 test: refactor to use "test_grep"
@@ Metadata
Author: Leon Michalak <[email protected]>
## Commit message ##
- test: refactor to use "test_grep"
+ test: use "test_grep"
- Refactor to use the modern "test_grep" test utility instead of regular
- "grep" which provides better debug information if tests fail.
+ Use the modern "test_grep" test utility instead of regular "grep" which
+ provides better debug information if tests fail.
This is a prerequisite to the commits that follow which add to both test files.
2: 75424cb8e1c ! 2: e5c40d37750 test: refactor to use "test_config"
@@ Metadata
Author: Leon Michalak <[email protected]>
## Commit message ##
- test: refactor to use "test_config"
+ test: use "test_config"
- Refactor to use the modern "test_config" test utility instead of manual
- "git config" as the former provides clean up on test completion.
+ Use the modern "test_config" test utility instead of manual"git config"
+ as the former provides clean up on test completion.
This is a prerequisite to the commits that follow which add to this test file.
3: f16d3de8611 ! 3: 1ec8a138486 add-patch: respect diff.context configuration
@@ Commit message
the user's diff.context and diff.interHunkContext file configurations.
This patch fixes this inconsistency.
+ This is because the plumbing commands used by "git add -p" to generate
+ the diff do not read those config settings. Fix this by reading the
+ config before generating the patch and passing it along to the diff
+ command with the "-U" and "--inter-hunk-context" command-line options.
+
Signed-off-by: Leon Michalak <[email protected]>
## add-interactive.c ##
@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repositor
+ die(_("%s cannot be negative"), "diff.context");
+ else
+ s->context = context;
-+ };
++ }
+ if (!repo_config_get_int(r, "diff.interHunkContext", &interhunkcontext)) {
+ if (interhunkcontext < 0)
+ die(_("%s cannot be negative"), "diff.interHunkContext");
+ else
+ s->interhunkcontext = interhunkcontext;
-+ };
++ }
+
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
if (s->use_single_key)
@@ add-patch.c: static int parse_diff(struct add_p_state *s, const struct pathspec
strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
if (s->revision) {
- ## t/t4055-diff-context.sh ##
-@@ t/t4055-diff-context.sh: test_expect_success 'diff.context honored by "log"' '
- test_grep "^ firstline" output
+ ## t/t3701-add-interactive.sh ##
+@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' '
+ test_cmp expect actual
'
-+test_expect_success 'diff.context honored by "add"' '
-+ git add -p >output &&
-+ test_grep ! firstline output &&
-+ test_config diff.context 8 &&
-+ git log -1 -p >output &&
-+ test_grep "^ firstline" output
-+'
-+
-+test_expect_success 'diff.context honored by "commit"' '
-+ ! git commit -p >output &&
-+ test_grep ! firstline output &&
-+ test_config diff.context 8 &&
-+ ! git commit -p >output &&
-+ test_grep "^ firstline" output
-+'
-+
-+test_expect_success 'diff.context honored by "checkout"' '
-+ git checkout -p >output &&
-+ test_grep ! firstline output &&
-+ test_config diff.context 8 &&
-+ git checkout -p >output &&
-+ test_grep "^ firstline" output
-+'
-+
-+test_expect_success 'diff.context honored by "stash"' '
-+ ! git stash -p >output &&
-+ test_grep ! firstline output &&
-+ test_config diff.context 8 &&
-+ ! git stash -p >output &&
-+ test_grep "^ firstline" output
++test_expect_success 'add -p respects diff.context' '
++ test_write_lines a b c d e f g h i j k l m >file &&
++ git add file &&
++ test_write_lines a b c d e f G h i j k l m >file &&
++ echo y | git -c diff.context=5 add -p >actual &&
++ test_grep "@@ -2,11 +2,11 @@" actual
+'
+
-+test_expect_success 'diff.context honored by "restore"' '
-+ git restore -p >output &&
-+ test_grep ! firstline output &&
-+ test_config diff.context 8 &&
-+ git restore -p >output &&
-+ test_grep "^ firstline" output
++test_expect_success 'add -p respects diff.interHunkContext' '
++ test_write_lines a b c d e f g h i j k l m n o p q r s >file &&
++ git add file &&
++ test_write_lines a b c d E f g i i j k l m N o p q r s >file &&
++ echo y | git -c diff.interhunkcontext=2 add -p >actual &&
++ test_grep "@@ -2,16 +2,16 @@" actual
+'
+
- test_expect_success 'The -U option overrides diff.context' '
- test_config diff.context 8 &&
- git log -U4 -1 >output &&
-@@ t/t4055-diff-context.sh: test_expect_success 'negative integer config parsing' '
- test_grep "bad config variable" output
- '
-
-+test_expect_success 'negative integer config parsing by "add"' '
++test_expect_success 'add -p rejects negative diff.context' '
+ test_config diff.context -1 &&
+ test_must_fail git add -p 2>output &&
+ test_grep "diff.context cannot be negative" output
+'
+
-+test_expect_success 'negative integer config parsing by "commit"' '
-+ test_config diff.context -1 &&
-+ test_must_fail git commit -p 2>output &&
-+ test_grep "bad config variable" output
-+'
-+
-+test_expect_success 'negative integer config parsing by "checkout"' '
-+ test_config diff.context -1 &&
-+ test_must_fail git checkout -p 2>output &&
-+ test_grep "diff.context cannot be negative" output
-+'
-+
-+test_expect_success 'negative integer config parsing by "stash"' '
-+ test_config diff.context -1 &&
-+ test_must_fail git stash -p 2>output &&
-+ test_grep "diff.context cannot be negative" output
-+'
-+
-+test_expect_success 'negative integer config parsing by "restore"' '
-+ test_config diff.context -1 &&
-+ test_must_fail git restore -p 2>output &&
-+ test_grep "diff.context cannot be negative" output
-+'
-+
- test_expect_success '-U0 is valid, so is diff.context=0' '
- test_config diff.context 0 &&
- git diff >output &&
+ test_done
4: 973dfadd1b3 ! 4: b68c58b667c add-patch: add diff.context command line overrides
@@ Documentation/git-checkout.adoc: section of linkgit:git-add[1] to learn how to o
+include::diff-context-options.adoc[]
+
- --ignore-other-worktrees::
+ `--ignore-other-worktrees`::
`git checkout` refuses when the wanted branch is already checked
out or otherwise in use by another worktree. This option makes
@@ builtin/add.c: static struct option builtin_add_options[] = {
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
+@@ builtin/add.c: int cmd_add(int argc,
+ prepare_repo_settings(repo);
+ repo->settings.command_requires_full_index = 0;
+
++ if (add_p_opt.context < -1)
++ die(_("'%s' cannot be negative"), "--unified");
++ if (add_p_opt.interhunkcontext < -1)
++ die(_("'%s' cannot be negative"), "--inter-hunk-context");
++
+ if (patch_interactive)
+ add_interactive = 1;
+ if (add_interactive) {
@@ builtin/add.c: int cmd_add(int argc,
die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
if (pathspec_from_file)
@@ builtin/checkout.c: static int checkout_paths(const struct checkout_opts *opts,
- &opts->pathspec);
+ return !!run_add_p(the_repository, patch_mode, &add_p_opt,
+ rev, &opts->pathspec);
-+ } else {
-+ if (opts->patch_context != -1)
-+ die(_("the option '%s' requires '%s'"), "--unified", "--patch");
-+ if (opts->patch_interhunk_context != -1)
-+ die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
}
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ builtin/checkout.c: static struct option *add_checkout_path_options(struct check
OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
N_("do not limit pathspecs to sparse entries only")),
OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
+@@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const char *prefix,
+ argc = parse_options(argc, argv, prefix, options,
+ usagestr, parseopt_flags);
+
++ if (opts->patch_context < -1)
++ die(_("'%s' cannot be negative"), "--unified");
++ if (opts->patch_interhunk_context < -1)
++ die(_("'%s' cannot be negative"), "--inter-hunk-context");
++
++ if (!opts->patch_mode) {
++ if (opts->patch_context != -1)
++ die(_("the option '%s' requires '%s'"), "--unified", "--patch");
++ if (opts->patch_interhunk_context != -1)
++ die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
++ }
++
+ if (opts->show_progress < 0) {
+ if (opts->quiet)
+ opts->show_progress = 0;
## builtin/commit.c ##
@@
@@ builtin/commit.c: static const char *edit_message, *use_message;
static int edit_flag = -1; /* unspecified */
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static int config_commit_verbose = -1; /* unspecified */
+@@ builtin/commit.c: static const char *prepare_index(const char **argv, const char *prefix,
+ const char *ret;
+ char *path = NULL;
+
++ if (add_p_opt.context < -1)
++ die(_("'%s' cannot be negative"), "--unified");
++ if (add_p_opt.interhunkcontext < -1)
++ die(_("'%s' cannot be negative"), "--inter-hunk-context");
++
+ if (is_status)
+ refresh_flags |= REFRESH_UNMERGED;
+ parse_pathspec(&pathspec, 0,
@@ builtin/commit.c: static const char *prepare_index(const char **argv, const char *prefix,
old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
@@ builtin/reset.c: int cmd_reset(int argc,
OPT_BOOL('N', "intent-to-add", &intent_to_add,
N_("record only the fact that removed paths will be added later")),
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
+@@ builtin/reset.c: int cmd_reset(int argc,
+ oidcpy(&oid, &tree->object.oid);
+ }
+
++ if (add_p_opt.context < -1)
++ die(_("'%s' cannot be negative"), "--unified");
++ if (add_p_opt.interhunkcontext < -1)
++ die(_("'%s' cannot be negative"), "--inter-hunk-context");
++
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
@@ builtin/reset.c: int cmd_reset(int argc,
if (reset_type != NONE)
die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
+ if (add_p_opt.interhunkcontext != -1)
+ die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
+ }
++
++ if (add_p_opt.context < -1)
++ die(_("'%s' cannot be negative"), "--unified");
++ if (add_p_opt.interhunkcontext < -1)
++ die(_("'%s' cannot be negative"), "--inter-hunk-context");
+
ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
- include_untracked, only_staged);
@@ builtin/stash.c: static int save_stash(int argc, const char **argv, const char *
memset(&ps, 0, sizeof(ps));
+
++ if (add_p_opt.context < -1)
++ die(_("'%s' cannot be negative"), "--unified");
++ if (add_p_opt.interhunkcontext < -1)
++ die(_("'%s' cannot be negative"), "--inter-hunk-context");
++
+ if (!patch_mode) {
+ if (add_p_opt.context != -1)
+ die(_("the option '%s' requires '%s'"), "--unified", "--patch");
@@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *
#define OPT_IPVERSION(v) \
OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
- ## t/t4032-diff-inter-hunk-context.sh ##
-@@ t/t4032-diff-inter-hunk-context.sh: t() {
- "
- }
+ ## t/t3701-add-interactive.sh ##
+@@ t/t3701-add-interactive.sh: test_expect_success 'add -p rejects negative diff.context' '
+ test_grep "diff.context cannot be negative" output
+ '
-+t_patch() {
-+ use_config=
-+ git config --unset diff.interHunkContext
-+
-+ case $# in
-+ 4) hunks=$4; cmd="add -p -U$3";;
-+ 5) hunks=$5; cmd="add -p -U$3 --inter-hunk-context=$4";;
-+ 6) hunks=$5; cmd="add -p -U$3"; git config diff.interHunkContext $4; use_config="(diff.interHunkContext=$4) ";;
-+ esac
-+ label="$use_config$cmd, $1 common $2"
-+ file=f$1
-+
-+ if ! test -f $file
-+ then
-+ f A $1 B >$file
-+ git add $file
-+ git commit -q -m. $file
-+ f X $1 Y >$file
-+ fi
-+
-+ test_expect_success "$label: count hunks ($hunks)" "
-+ test $(test_write_lines q | git $cmd $file | sed -n 's/^([0-9]*\/\([0-9]*\)) Stage this hunk.*/\1/p') = $hunks
++for cmd in add checkout restore 'commit -m file'
++do
++ test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" "
++ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
++ git add file &&
++ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
++ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
++ $cmd -p -U 4 --inter-hunk-context 2 >actual &&
++ test_grep \"@@ -2,20 +2,20 @@\" actual
+ "
-+}
++done
++
++test_expect_success 'reset accepts -U and --inter-hunk-context' '
++ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
++ git commit -m file file &&
++ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
++ git add file &&
++ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
++ reset -p -U 4 --inter-hunk-context 2 >actual &&
++ test_grep "@@ -2,20 +2,20 @@" actual
++'
++
++test_expect_success 'stash accepts -U and --inter-hunk-context' '
++ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
++ git commit -m file file &&
++ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
++ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
++ stash -p -U 4 --inter-hunk-context 2 >actual &&
++ test_grep "@@ -2,20 +2,20 @@" actual
++'
++
++for cmd in add checkout commit reset restore 'stash save' 'stash push'
++do
++ test_expect_success "$cmd rejects invalid context options" "
++ test_must_fail git $cmd -p -U -3 2>actual &&
++ cat actual | echo &&
++ test_grep -e \"'--unified' cannot be negative\" actual &&
++
++ test_must_fail git $cmd -p --inter-hunk-context -3 2>actual &&
++ test_grep -e \"'--inter-hunk-context' cannot be negative\" actual &&
++
++ test_must_fail git $cmd -U 7 2>actual &&
++ test_grep -E \"'--unified' requires '(--interactive/)?--patch'\" actual &&
++
++ test_must_fail git $cmd --inter-hunk-context 2 2>actual &&
++ test_grep -E \"'--inter-hunk-context' requires '(--interactive/)?--patch'\" actual
++ "
++done
+
- cat <<EOF >expected.f1.0.1 || exit 1
- diff --git a/f1 b/f1
- --- a/f1
-@@ t/t4032-diff-inter-hunk-context.sh: t 3 lines 1 2 1 config
- t 9 lines 3 2 2 config
- t 9 lines 3 3 1 config
-
-+# common lines ctx intrctx hunks
-+t_patch 1 line 0 2
-+t_patch 1 line 0 0 2
-+t_patch 1 line 0 1 1
-+t_patch 1 line 0 2 1
-+t_patch 1 line 1 1
-+
-+t_patch 2 lines 0 2
-+t_patch 2 lines 0 0 2
-+t_patch 2 lines 0 1 2
-+t_patch 2 lines 0 2 1
-+t_patch 2 lines 1 1
-+
-+t_patch 3 lines 1 2
-+t_patch 3 lines 1 0 2
-+t_patch 3 lines 1 1 1
-+t_patch 3 lines 1 2 1
-+
-+t_patch 9 lines 3 2
-+t_patch 9 lines 3 2 2
-+t_patch 9 lines 3 3 1
-+
-+# use diff.interHunkContext?
-+t_patch 1 line 0 0 2 config
-+t_patch 1 line 0 1 1 config
-+t_patch 1 line 0 2 1 config
-+t_patch 9 lines 3 3 1 config
-+t_patch 2 lines 0 0 2 config
-+t_patch 2 lines 0 1 2 config
-+t_patch 2 lines 0 2 1 config
-+t_patch 3 lines 1 0 2 config
-+t_patch 3 lines 1 1 1 config
-+t_patch 3 lines 1 2 1 config
-+t_patch 9 lines 3 2 2 config
-+t_patch 9 lines 3 3 1 config
-+
- test_expect_success 'diff.interHunkContext invalid' '
- git config diff.interHunkContext asdf &&
- test_must_fail git diff &&
+ test_done
## t/t4055-diff-context.sh ##
@@ t/t4055-diff-context.sh: test_expect_success 'The -U option overrides diff.context' 'Signature · 1 line
gitgitgadget
PATCH v3 1/4 test: use "test_grep"
From: Leon Michalak <[email protected]>
Use the modern "test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.
This is a prerequisite to the commits that follow which add to both test files.
--- t/t3701-add-interactive.sh | 48 +++++++++++++++++++------------------- t/t4055-diff-context.sh | 28 +++++++++++----------- 2 files changed, 38 insertions(+), 38 deletions(-)
t/t3701-add-interactive.sh +24 -24
@@ -63,7 +63,7 @@ test_expect_success 'setup (initial)' ' ' test_expect_success 'status works (initial)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'setup expected' '
@@ -86,7 +86,7 @@ test_expect_success 'revert works (initial)' ' git add file && test_write_lines r 1 | git add -i && git ls-files >output && - ! grep . output + test_grep ! . output ' test_expect_success 'add untracked (multiple)' '
@@ -109,7 +109,7 @@ test_expect_success 'setup (commit)' ' ' test_expect_success 'status works (commit)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'update can stage deletions' '
@@ -141,7 +141,7 @@ test_expect_success 'revert works (commit)' ' git add file && test_write_lines r 1 | git add -i && git add -i </dev/null >output && - grep "unchanged *+3/-0 file" output + test_grep "unchanged *+3/-0 file" output ' test_expect_success 'reject multi-key input' '
@@ -185,7 +185,7 @@ test_expect_success 'setup fake editor' ' test_expect_success 'bad edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -198,7 +198,7 @@ test_expect_success 'setup patch' ' test_expect_success 'garbage edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -313,8 +313,8 @@ test_expect_success FILEMODE 'stage mode and hunk' ' chmod +x file && printf "y\\ny\\n" | git add -p && git diff --cached file >out && - grep "new mode" out && - grep "+content" out && + test_grep "new mode" out && + test_grep "+content" out && git diff file >out && test_must_be_empty out '
@@ -636,7 +636,7 @@ test_expect_success 'split hunk "add -p (edit)"' ' printf "%s\n" s e q n q q | EDITOR=: git add -p && git diff >actual && - ! grep "^+15" actual + test_grep ! "^+15" actual ' test_expect_success 'split hunk "add -p (no, yes, edit)"' '
@@ -648,7 +648,7 @@ test_expect_success 'split hunk "add -p (no, yes, edit)"' ' EDITOR=: git add -p 2>error && test_must_be_empty error && git diff >actual && - ! grep "^+31" actual + test_grep ! "^+31" actual ' test_expect_success 'split hunk with incomplete line at end' '
@@ -682,7 +682,7 @@ test_expect_success 'edit, adding lines to the first hunk' ' EDITOR=./fake_editor.sh git add -p 2>error && test_must_be_empty error && git diff --cached >actual && - grep "^+22" actual + test_grep "^+22" actual ' test_expect_success 'patch mode ignores unmerged entries' '
@@ -696,7 +696,7 @@ test_expect_success 'patch mode ignores unmerged entries' ' test_must_fail git merge side && echo changed >non-conflict.t && echo y | git add -p >output && - ! grep a/conflict.t output && + test_grep ! a/conflict.t output && cat >expected <<-\EOF && * Unmerged path conflict.t diff --git a/non-conflict.t b/non-conflict.t
@@ -728,7 +728,7 @@ test_expect_success 'diffs can be colorized' ' # We do not want to depend on the exact coloring scheme # git uses for diffs, so just check that we saw some kind of color. - grep "$(printf "\\033")" output + test_grep "$(printf "\\033")" output ' test_expect_success 'colors can be overridden' '
@@ -743,7 +743,7 @@ test_expect_success 'colors can be overridden' ' -c color.interactive.error=blue \ add -i 2>err.raw <input && test_decode_color <err.raw >err && - grep "<BLUE>Huh (trigger)?<RESET>" err && + test_grep "<BLUE>Huh (trigger)?<RESET>" err && test_write_lines help quit >input && force_color git \
@@ -863,7 +863,7 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' printf y >y && force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y && test_decode_color <output.raw >output && - grep "old<" output + test_grep "old<" output ' test_expect_success 'diffFilter filters diff' '
@@ -876,7 +876,7 @@ test_expect_success 'diffFilter filters diff' ' # avoid depending on the exact coloring or content of the prompts, # and just make sure we saw our diff prefixed - grep foo:.*content output + test_grep foo:.*content output ' test_expect_success 'detect bogus diffFilter output' '
@@ -886,7 +886,7 @@ test_expect_success 'detect bogus diffFilter output' ' test_config interactive.diffFilter "sed 6d" && printf y >y && force_color test_must_fail git add -p <y >output 2>&1 && - grep "mismatched output" output + test_grep "mismatched output" output ' test_expect_success 'handle iffy colored hunk headers' '
@@ -896,7 +896,7 @@ test_expect_success 'handle iffy colored hunk headers' ' printf n >n && force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \ add -p >output 2>&1 <n && - grep "^XX$" output + test_grep "^XX$" output ' test_expect_success 'handle very large filtered diff' '
@@ -1002,7 +1002,7 @@ test_expect_success 'add -p does not expand argument lists' ' # update it, but we want to be sure that our "." pathspec # was not expanded into the argument list of any command. # So look only for "not-changed". - ! grep -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out + test_grep ! -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out ' test_expect_success 'hunk-editing handles custom comment char' '
@@ -1072,21 +1072,21 @@ test_expect_success 'setup different kinds of dirty submodules' ' test_expect_success 'status ignores dirty submodules (except HEAD)' ' git -C for-submodules add -i </dev/null >output && - grep dirty-head output && - grep dirty-both-ways output && - ! grep dirty-otherwise output + test_grep dirty-head output && + test_grep dirty-both-ways output && + test_grep ! dirty-otherwise output ' test_expect_success 'handle submodules' ' echo 123 >>for-submodules/dirty-otherwise/initial.t && force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 && - grep "No changes" output && + test_grep "No changes" output && force_color git -C for-submodules add -p dirty-head >output 2>&1 <y && git -C for-submodules ls-files --stage dirty-head >actual && rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" && - grep "$rev" actual + test_grep "$rev" actual ' test_expect_success 'set up pathological context' '
t/t4055-diff-context.sh +14 -14
@@ -38,36 +38,36 @@ test_expect_success 'setup' ' test_expect_success 'the default number of context lines is 3' ' git diff >output && - ! grep "^ d" output && - grep "^ e" output && - grep "^ j" output && - ! grep "^ k" output + test_grep ! "^ d" output && + test_grep "^ e" output && + test_grep "^ j" output && + test_grep ! "^ k" output ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && - ! grep firstline output && + test_grep ! firstline output && git config diff.context 8 && git log -1 -p >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' git config diff.context 8 && git log -U4 -1 >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' git config diff.context 8 && git diff >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' git config diff.context 8 && git diff-files -p >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' '
@@ -85,8 +85,8 @@ test_expect_success 'negative integer config parsing' ' test_expect_success '-U0 is valid, so is diff.context=0' ' git config diff.context 0 && git diff >output && - grep "^-ADDED" output && - grep "^+MODIFIED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output ' test_expect_success '-U2147483647 works' '
@@ -94,9 +94,9 @@ test_expect_success '-U2147483647 works' ' test_line_count = 16 x && git diff -U2147483647 >output && test_line_count = 22 output && - grep "^-ADDED" output && - grep "^+MODIFIED" output && - grep "^+APPENDED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output && + test_grep "^+APPENDED" output ' test_done
Signature · 1 line
gitgitgadget
PATCH v3 2/4 test: use "test_config"
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Use the modern "test_config" test utility instead of manual"git config" as the former provides clean up on test completion.
This is a prerequisite to the commits that follow which add to this test file.
--- t/t4055-diff-context.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
t/t4055-diff-context.sh +7 -7
@@ -47,43 +47,43 @@ test_expect_success 'the default number of context lines is 3' ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && test_grep ! firstline output && - git config diff.context 8 && + test_config diff.context 8 && git log -1 -p >output && test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' - git config diff.context 8 && + test_config diff.context 8 && git log -U4 -1 >output && test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' - git config diff.context 8 && + test_config diff.context 8 && git diff >output && test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' - git config diff.context 8 && + test_config diff.context 8 && git diff-files -p >output && test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' ' - git config diff.context no && + test_config diff.context no && test_must_fail git diff 2>output && test_grep "bad numeric config value" output ' test_expect_success 'negative integer config parsing' ' - git config diff.context -1 && + test_config diff.context -1 && test_must_fail git diff 2>output && test_grep "bad config variable" output ' test_expect_success '-U0 is valid, so is diff.context=0' ' - git config diff.context 0 && + test_config diff.context 0 && git diff >output && test_grep "^-ADDED" output && test_grep "^+MODIFIED" output
Signature · 1 line
gitgitgadget
PATCH v3 3/4 add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations. This patch fixes this inconsistency.
This is because the plumbing commands used by "git add -p" to generate the diff do not read those config settings. Fix this by reading the config before generating the patch and passing it along to the diff command with the "-U" and "--inter-hunk-context" command-line options.
--- add-interactive.c | 17 +++++++++++++++++ add-interactive.h | 1 + add-patch.c | 6 ++++++ t/t3701-add-interactive.sh | 22 ++++++++++++++++++++++ 4 files changed, 46 insertions(+)
add-interactive.c +17 -0
@@ -39,8 +39,12 @@ static void init_color(struct repository *r, struct add_i_state *s,void init_add_i_state (struct add_i_state *s,struct repository *r) {const char *value; +int context; +int interhunkcontext; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;
@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &context)) { +if (context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +else + s->context = context; + } +if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + } +repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL );
add-interactive.h +1 -0
@@ -18,6 +18,7 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; };void init_add_i_state (struct add_i_state *s,struct repository *r);
add-patch.c +6 -0
@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) {struct strvec args =STRVEC_INIT ;const char *diff_algorithm = s->s.interactive_diff_algorithm; +int diff_context = s->s.context; +int diff_interhunkcontext = s->s.interhunkcontext;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;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)int res;strvec_pushv (&args, s->mode->diff_cmd); +if (diff_context !=-1 ) +strvec_pushf (&args,"--unified=%i" , diff_context); +if (diff_interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , diff_interhunkcontext);if (diff_algorithm)strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm);if (s->revision) {
t/t3701-add-interactive.sh +22 -0
@@ -1230,4 +1230,26 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'add -p respects diff.context' ' + test_write_lines a b c d e f g h i j k l m >file && + git add file && + test_write_lines a b c d e f G h i j k l m >file && + echo y | git -c diff.context=5 add -p >actual && + test_grep "@@ -2,11 +2,11 @@" actual +' + +test_expect_success 'add -p respects diff.interHunkContext' ' + test_write_lines a b c d e f g h i j k l m n o p q r s >file && + git add file && + test_write_lines a b c d E f g i i j k l m N o p q r s >file && + echo y | git -c diff.interhunkcontext=2 add -p >actual && + test_grep "@@ -2,16 +2,16 @@" actual +' + +test_expect_success 'add -p rejects negative diff.context' ' + test_config diff.context -1 && + test_must_fail git add -p 2>output && + test_grep "diff.context cannot be negative" output +' + test_done
Signature · 1 line
gitgitgadget
PATCH v3 4/4 add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
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.
--- Documentation/diff-context-options.adoc | 10 +++++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 36 ++++++++++++---- add-interactive.h | 16 +++++-- add-patch.c | 5 ++- builtin/add.c | 21 ++++++++-- builtin/checkout.c | 31 ++++++++++++-- builtin/commit.c | 16 ++++++- builtin/reset.c | 17 +++++++- builtin/stash.c | 56 ++++++++++++++++++++----- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 49 ++++++++++++++++++++++ t/t4055-diff-context.sh | 30 +++++++++++++ t/t9902-completion.sh | 2 + 20 files changed, 271 insertions(+), 35 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
Documentation/diff-context-options.adoc new file +10 -0
@@ -0,0 +1,10 @@ +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset.
Documentation/git-add.adoc +2 -0
@@ -104,6 +104,8 @@ This effectively runs `add --interactive`, but bypasses the initial command menu and directly jumps to the `patch` subcommand. See ``Interactive mode'' for details. +include::diff-context-options.adoc[] + `-e`:: `--edit`:: Open the diff vs. the index in an editor and let the user
Documentation/git-checkout.adoc +2 -0
@@ -289,6 +289,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. +include::diff-context-options.adoc[] + `--ignore-other-worktrees`:: `git checkout` refuses when the wanted branch is already checked out or otherwise in use by another worktree. This option makes
Documentation/git-commit.adoc +2 -0
@@ -76,6 +76,8 @@ OPTIONS which changes to commit. See linkgit:git-add[1] for details. +include::diff-context-options.adoc[] + `-C <commit>`:: `--reuse-message=<commit>`:: Take an existing _<commit>_ object, and reuse the log message
Documentation/git-reset.adoc +2 -0
@@ -125,6 +125,8 @@ OPTIONS separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). +include::diff-context-options.adoc[] + `--`:: Do not interpret any more arguments as options.
Documentation/git-restore.adoc +2 -0
@@ -52,6 +52,8 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. +include::diff-context-options.adoc[] + `-W`:: `--worktree`:: `-S`::
Documentation/git-stash.adoc +2 -0
@@ -208,6 +208,8 @@ to learn how to operate the `--patch` mode. The `--patch` option implies `--keep-index`. You can use `--no-keep-index` to override this. +include::diff-context-options.adoc[] + -S:: --staged:: This option is only valid for `push` and `save` commands.
add-interactive.c +28 -8
@@ -36,7 +36,8 @@ static void init_color(struct repository *r, struct add_i_state *s,free (key); } -void init_add_i_state (struct add_i_state *s,struct repository *r) +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt) {const char *value;int context;
@@ -98,6 +99,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); + +if (add_p_opt->context !=-1 ) { +if (add_p_opt->context <0 ) +die (_ ("%s cannot be negative" ),"--unified" ); + s->context = add_p_opt->context; + } +if (add_p_opt->interhunkcontext !=-1 ) { +if (add_p_opt->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"--inter-hunk-context" ); + s->interhunkcontext = add_p_opt->interhunkcontext; + } }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, opts->prompt =N_ ("Patch update" ); count =list_and_choose (s, files, opts);if (count >0 ) { +struct add_p_opt add_p_opt = { + .context = s->context, + .interhunkcontext = s->interhunkcontext, + };struct strvec args =STRVEC_INIT ;struct pathspec ps_selected = {0 };
@@ -996,7 +1012,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,parse_pathspec (&ps_selected,PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL ,PATHSPEC_LITERAL_PATH ,"" , args.v); - res =run_add_p (s->r,ADD_P_ADD ,NULL , &ps_selected); + res =run_add_p (s->r,ADD_P_ADD , &add_p_opt,NULL , &ps_selected);strvec_clear (&args);clear_pathspec (&ps_selected); }
@@ -1031,10 +1047,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; -strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" , -oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), -"--" ,NULL ); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );for (i =0 ; i < files->items.nr; i++)if (files->selected[i]) strvec_push(&cmd.args,
@@ -1127,7 +1146,8 @@ static void command_prompt_help(struct add_i_state *s) _("(empty) select nothing")); } -int run_add_i (struct repository *r,const struct pathspec *ps) +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt) {struct add_i_state s = {NULL };struct print_command_item_data data = {"[" ,"]" };
@@ -1170,7 +1190,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps) ->util = util; } -init_add_i_state (&s, r); +init_add_i_state (&s, r, add_p_opt);/* * When color was asked for, use the prompt color for
add-interactive.h +13 -3
@@ -3,6 +3,13 @@#include "color.h" +struct add_p_opt { +int context; +int interhunkcontext; +}; + +#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 } +struct add_i_state {struct repository *r;int use_color;
@@ -21,12 +28,14 @@ struct add_i_state {int context, interhunkcontext; }; -void init_add_i_state (struct add_i_state *s,struct repository *r); +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt);void clear_add_i_state (struct add_i_state *s);struct repository ;struct pathspec ; -int run_add_i (struct repository *r,const struct pathspec *ps); +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt);enum add_p_mode {ADD_P_ADD ,
@@ -37,6 +46,7 @@ enum add_p_mode { };int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps); +struct add_p_opt *o,const char *revision, +const struct pathspec *ps);#endif
add-patch.c +3 -2
@@ -1766,14 +1766,15 @@ soft_increment: }int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps) +struct add_p_opt *o,const char *revision, +const struct pathspec *ps) {struct add_p_state s = { { r },STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT };size_t i, binary_count =0 ; -init_add_i_state (&s.s, r); +init_add_i_state (&s.s, r, o);if (mode ==ADD_P_STASH ) s.mode = &patch_mode_stash;
builtin/add.c +17 -4
@@ -29,6 +29,7 @@ static const char * const builtin_add_usage[] = { NULL };static int patch_interactive, add_interactive, edit_interactive; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int take_worktree_changes;static int add_renormalize;static int pathspec_file_nul;
@@ -157,7 +158,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch) +int patch,struct add_p_opt *add_p_opt) {struct pathspec pathspec;int ret;
@@ -169,9 +170,9 @@ int interactive_add(struct repository *repo, prefix, argv);if (patch) - ret = !!run_add_p (repo,ADD_P_ADD ,NULL , &pathspec); + ret = !!run_add_p (repo,ADD_P_ADD , add_p_opt,NULL , &pathspec);else - ret = !!run_add_i (repo, &pathspec); + ret = !!run_add_i (repo, &pathspec, add_p_opt);clear_pathspec (&pathspec);return ret;
@@ -253,6 +254,8 @@ static struct option builtin_add_options[] = {OPT_GROUP ("" ),OPT_BOOL ('i' ,"interactive" , &add_interactive,N_ ("interactive picking" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('e' ,"edit" , &edit_interactive,N_ ("edit current diff and apply" )),OPT__FORCE (&ignored_too,N_ ("allow adding otherwise ignored files" ),0 ), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -394,6 +397,11 @@ int cmd_add(int argc,prepare_repo_settings (repo); repo->settings.command_requires_full_index =0 ; +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +if (patch_interactive) add_interactive =1 ;if (add_interactive) {
@@ -401,7 +409,12 @@ int cmd_add(int argc,die (_ ("options '%s' and '%s' cannot be used together" ),"--dry-run" ,"--interactive/--patch" );if (pathspec_from_file)die (_ ("options '%s' and '%s' cannot be used together" ),"--pathspec-from-file" ,"--interactive/--patch" ); -exit (interactive_add (repo, argv +1 , prefix, patch_interactive)); +exit (interactive_add (repo, argv +1 , prefix, patch_interactive, &add_p_opt)); + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }if (edit_interactive) {
builtin/checkout.c +28 -3
@@ -61,6 +61,8 @@ static const char * const restore_usage[] = {struct checkout_opts {int patch_mode; +int patch_context; +int patch_interhunk_context;int quiet;int merge;int force;
@@ -104,7 +106,12 @@ struct checkout_opts {struct tree *source_tree; }; -#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 } +#define CHECKOUT_OPTS_INIT { \ + .conflict_style = -1, \ + .merge = -1, \ + .patch_context = -1, \ + .patch_interhunk_context = -1, \ +}struct branch_info {char *name;/* The short name used */
@@ -539,6 +546,10 @@ static int checkout_paths(const struct checkout_opts *opts,if (opts->patch_mode) {enum add_p_mode patch_mode; +struct add_p_opt add_p_opt = { + .context = opts->patch_context, + .interhunkcontext = opts->patch_interhunk_context, + };const char *rev = new_branch_info->name;char rev_oid[GIT_MAX_HEXSZ +1 ];
@@ -564,8 +575,8 @@ static int checkout_paths(const struct checkout_opts *opts,else BUG ("either flag must have been set, worktree=%d, index=%d" , opts->checkout_worktree, opts->checkout_index); -return !!run_add_p (the_repository, patch_mode, rev, - &opts->pathspec); +return !!run_add_p (the_repository, patch_mode, &add_p_opt, + rev, &opts->pathspec); }repo_hold_locked_index (the_repository, &lock_file,LOCK_DIE_ON_ERROR );
@@ -1738,6 +1749,8 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts, N_("checkout their version for unmerged files"), 3, PARSE_OPT_NONEG),OPT_BOOL ('p' ,"patch" , &opts->patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&opts->patch_context), +OPT_DIFF_INTERHUNK_CONTEXT (&opts->patch_interhunk_context),OPT_BOOL (0 ,"ignore-skip-worktree-bits" , &opts->ignore_skipworktree,N_ ("do not limit pathspecs to sparse entries only" )), OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
@@ -1780,6 +1793,18 @@ static int checkout_main(int argc, const char **argv, const char *prefix, argc =parse_options (argc, argv, prefix, options, usagestr, parseopt_flags); +if (opts->patch_context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (opts->patch_interhunk_context <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); + +if (!opts->patch_mode) { +if (opts->patch_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (opts->patch_interhunk_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); + } +if (opts->show_progress <0 ) {if (opts->quiet) opts->show_progress =0 ;
builtin/commit.c +15 -1
@@ -19,6 +19,7 @@#include "environment.h" #include "diff.h" #include "commit.h" +#include "add-interactive.h" #include "gettext.h" #include "revision.h" #include "wt-status.h"
@@ -122,6 +123,7 @@ static const char *edit_message, *use_message;static char *fixup_message, *fixup_commit, *squash_message;static const char *fixup_prefix;static int all, also, interactive, patch_interactive, only, amend, signoff; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int edit_flag =-1 ;/* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */
@@ -354,6 +356,11 @@ static const char *prepare_index(const char **argv, const char *prefix,const char *ret;char *path =NULL ; +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +if (is_status) refresh_flags |=REFRESH_UNMERGED ; parse_pathspec(&pathspec, 0,
@@ -400,7 +407,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env =xstrdup_or_null (getenv (INDEX_ENVIRONMENT ));setenv (INDEX_ENVIRONMENT , the_repository->index_file,1 ); -if (interactive_add (the_repository, argv, prefix, patch_interactive) !=0 ) +if (interactive_add (the_repository, argv, prefix, patch_interactive, &add_p_opt) !=0 )die (_ ("interactive add failed" )); the_repository->index_file = old_repo_index_file;
@@ -424,6 +431,11 @@ static const char *prepare_index(const char **argv, const char *prefix, commit_style =COMMIT_NORMAL ; ret =get_lock_file_path (&index_lock); goto out; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }/*
@@ -1722,6 +1734,8 @@ int cmd_commit(int argc,OPT_BOOL ('i' ,"include" , &also,N_ ("add specified files to index for commit" )),OPT_BOOL (0 ,"interactive" , &interactive,N_ ("interactively add files" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("interactively add changes" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('o' ,"only" , &only,N_ ("commit only specified files" )),OPT_BOOL ('n' ,"no-verify" , &no_verify,N_ ("bypass pre-commit and commit-msg hooks" )), OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
builtin/reset.c +15 -2
@@ -346,6 +346,7 @@ int cmd_reset(int argc,struct object_id oid;struct pathspec pathspec;int intent_to_add =0 ; +struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;const struct option options[] = {OPT__QUIET (&quiet,N_ ("be quiet, only report errors" )), OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -370,6 +371,8 @@ int cmd_reset(int argc, PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),OPT_BOOL ('p' ,"patch" , &patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('N' ,"intent-to-add" , &intent_to_add,N_ ("record only the fact that removed paths will be added later" )), OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -420,6 +423,11 @@ int cmd_reset(int argc,oidcpy (&oid, &tree->object.oid); } +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +prepare_repo_settings (the_repository); the_repository->settings.command_requires_full_index =0 ;
@@ -427,9 +435,14 @@ int cmd_reset(int argc,if (reset_type !=NONE )die (_ ("options '%s' and '%s' cannot be used together" ),"--patch" ,"--{hard,mixed,soft}" );trace2_cmd_mode ("patch-interactive" ); - update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , rev, - &pathspec); + update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , + &add_p_opt, rev, &pathspec); goto cleanup; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }/* git reset tree [--] paths... can be used to
builtin/stash.c +45 -11
136 lines not on this page · raw message
commit.h +2 -1
@@ -2,6 +2,7 @@#define COMMIT_H #include "object.h" +#include "add-interactive.h" struct signature_check ;struct strbuf ;
@@ -257,7 +258,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch); +int patch,struct add_p_opt *add_p_opt);struct commit_extra_header {struct commit_extra_header *next;
parse-options.h +2 -0
@@ -616,6 +616,8 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);#define OPT_PATHSPEC_FROM_FILE (v) OPT_FILENAME(0, "pathspec-from-file", v, N_("read pathspec from file"))#define OPT_PATHSPEC_FILE_NUL (v) OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))#define OPT_AUTOSTASH (v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after")) +#define OPT_DIFF_UNIFIED (v) OPT_INTEGER_F('U', "unified", v, N_("generate diffs with <n> lines context"), PARSE_OPT_NONEG) +#define OPT_DIFF_INTERHUNK_CONTEXT (v) OPT_INTEGER_F(0, "inter-hunk-context", v, N_("show context between diff hunks up to the specified number of lines"), PARSE_OPT_NONEG)#define OPT_IPVERSION (v) \ OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
t/t3701-add-interactive.sh +49 -0
53 lines not on this page · raw message
t/t4055-diff-context.sh +30 -0
@@ -58,6 +58,36 @@ test_expect_success 'The -U option overrides diff.context' ' test_grep ! "^ firstline" output ' +test_expect_success 'The -U option overrides diff.context for "add"' ' + test_config diff.context 8 && + git add -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "commit"' ' + test_config diff.context 8 && + ! git commit -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "checkout"' ' + test_config diff.context 8 && + git checkout -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "stash"' ' + test_config diff.context 8 && + ! git stash -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "restore"' ' + test_config diff.context 8 && + git restore -U4 -p >output && + test_grep ! "^ firstline" output +' + test_expect_success 'diff.context honored by "diff"' ' test_config diff.context 8 && git diff >output &&
t/t9902-completion.sh +2 -0
@@ -2596,6 +2596,8 @@ test_expect_success 'double dash "git checkout"' ' --merge Z --conflict=Z --patch Z + --unified=Z + --inter-hunk-context=Z --ignore-skip-worktree-bits Z --ignore-other-worktrees Z --recurse-submodules Z
Signature · 1 line
gitgitgadget
Quoted 3 lines · Leon Michalak via GitGitGadget
Leon Michalak (4):
test: use "test_grep"
test: use "test_config"
These make it sound as if they touch all test scripts under t/ but apparently that is not what this series is doing (and we do not want to see a huge churn like that anyway). Would something like
t: use test_grep in t3701, t4055, and t9902
work better?
Quoted 2 lines
add-patch: respect diff.context configuration
add-patch: add diff.context command line overrides
Re: [PATCH v3 1/4] test: use "test_grep"
In reply to Leon Michalak via GitGitGadgetQuoted 7 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Use the modern "
test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.This is a prerequisite to the commits that follow which add to both test files.
Just a terminology thing, but we would phrase the last paragraph more like
As a preparatory clean-up, use the "test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.
to avoid saying "This does X", "This commit is Y", etc. It also avoids giving a wrong impression by misusing the word "prerequisite" which we almost always use for a step that cannot be skipped. While we add new tests to the same file, we _could_ leave these existing tests as-is, but there is a good reason to making this change beforehand, which we often call is a "preparatory clean-up".
t/t3701-add-interactive.sh test_expect_success 'revert works (initial)' ' · line 90
Quoted 7 lines
t/t3701-add-interactive.sh +1
-1@@ -86,7 +86,7 @@ test_expect_success 'revert works (initial)' ' git add file && test_write_lines r 1 | git add -i && git ls-files >output && - ! grep . output + test_grep ! . output '
Good (we sometime see people got the negation wrong).
Thanks.
Re: [PATCH v3 2/4] test: use "test_config"
In reply to Leon Michalak via GitGitGadgetQuoted 4 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Use the modern "
test_config" test utility instead of manual"git config" as the former provides clean up on test completion.
Here "completion" is not "all the tests in the script are done", but "each of the test_expect_{success,failure} piece that uses test_config".
Drop "modern". It was invented 14 years ago (the same can be said for test_grep which was called test_i18ngrep and had an extra purpose, which was invented in the same year).
This conversion, unlike "test_grep" needs to be done a bit carefully. The fact the configuration is removed after the test piece "test_config" was used means any tests after the test that was originally using "git config" needs to be inspected to make sure it was *not* relying on the value that was left by the previous test piece.
For example...
t/t4055-diff-context.sh test_expect_success 'the default number of context lines is 3' ' · line 53
Quoted 8 lines
test_expect_success'diff.context honored by "log"' 't/t4055-diff-context.sh +1
-1git log -1 -p >output && test_grep ! firstline output && - git config diff.context 8 && + test_config diff.context 8 && git log -1 -p >output && test_grep "^ firstline" output '
... the test piece after this one may have assumed (wrongly! The assumption does not hold if this test failed before reaching "git config") that diff.context is still set to 8 but that is no longer the case. But that one is OK because ...
t/t4055-diff-context.sh test_expect_success 'the default number of context lines is 3' ' · line 59
Quoted 6 lines
test_expect_success'The -U option overrides diff.context' 't/t4055-diff-context.sh +1
-1- git config diff.context 8 && + test_config diff.context 8 && git log -U4 -1 >output && test_grep ! "^ firstline" output '
... it was setting it for itself. The same can be said with other tests (not quoted in this reply). They all set things up for themselves, which is a good hygiene.
That means the last one in the patch needs to be inspected carefully. We do not know from the post-context of the patch what the next test used to expect.
t/t4055-diff-context.sh test_expect_success 'the default number of context lines is 3' ' · line 89
Quoted 6 lines
test_expect_success'-U0 is valid, so is diff.context=0' 't/t4055-diff-context.sh +1
-1- git config diff.context 0 && + test_config diff.context 0 && git diff >output && test_grep "^-ADDED" output && test_grep "^+MODIFIED" output
The one that comes after this one is about giving an explicit command line option -U<n>. It should not be affected by a diff.context conffiguration variable that is lower-precedence so we should be OK.
Thanks.
Re: [PATCH v3 3/4] add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetQuoted 4 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations.
Great. "add-patch.c" invokes "diff-files", "diff-index" plumbing commands to do its thing, and these plumbing commands deliberately ignore such configuration variables, unlike "diff" Porcelain command that is meant for end-user consumption.
Quoted 1 line
This patch fixes this inconsistency.
If we were spelling it out, we would say "Fix this inconsistency" in imperative. But you never talked about "this inconsistency" so far, so it is not just confusing. It hints an incorrect conclusion that the difference between plumbing diff-{files,index,tree} and Porcelain diff is an inconsistency that needs to be "fixed", which is not true.
Follow the first paragraph with an explanation why it is a bad thing. For example:
The user may be used to seeing their diffs with customized context size, but not in the patches "git add -p" shows them to pick from.
That would implicitly tell readers that we would want the patch shown by "add -p" generated with diff.context given by the user. So we can outline the solution next.
Teach add-patch infrastructure to read these configuration variables and pass their values when spawning the underlying plumbing commands as their command line option.
or something.
add-interactive.c static void init_color(struct repository *r, struct add_i_state *s, · line 47
Quoted 10 lines
add-interactive.c +4
-0@@ -39,8 +39,12 @@ static void init_color(struct repository *r, struct add_i_state *s,void init_add_i_state (struct add_i_state *s,struct repository *r) {const char *value; +int context; +int interhunkcontext; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;
Hmph, context/interhunkcontext variables serve no purpose other than peeking into the value before assigning it to s->{context,interhunkcontext} members. In a sense, they may be confusing than they are worth.
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 90
Quoted 12 lines
add-interactive.c +6
-0if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &context)) { +if (context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +else + s->context = context; + }
Would the code be easier to understand if it is written more like
if (!repo_config_get_int(r, "diff.context", &s->context)) {
if (s->context < 0)
die(...);
}with or without {braces} around the (technically) single statement block?
add-interactive.c void init_add_i_state(struct add_i_state *s, struct repository *r) · line 96
Quoted 6 lines
add-interactive.c +6
-0+if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + }
Ditto.
Quoted 26 lines
add-interactive.h +1
-0@@ -18,6 +18,7 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; };void init_add_i_state (struct add_i_state *s,struct repository *r);add-patch.c +2
-0@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) {struct strvec args =STRVEC_INIT ;const char *diff_algorithm = s->s.interactive_diff_algorithm; +int diff_context = s->s.context; +int diff_interhunkcontext = s->s.interhunkcontext;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;char *p, *pend, *colored_p =NULL , *colored_pend =NULL , marker ='\0' ;
add-patch.c static int parse_diff(struct add_p_state *s, const struct pathspec *ps) · line 432
Quoted 7 lines
add-patch.c +4
-0@@ -424,6 +426,10 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)int res;strvec_pushv (&args, s->mode->diff_cmd); +if (diff_context !=-1 ) +strvec_pushf (&args,"--unified=%i" , diff_context); +if (diff_interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , diff_interhunkcontext);
Ditto. What does it buy us to have these two local variables? We have the state object 's' available to us here, right?
Thanks.
Re: [PATCH v3 4/4] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetQuoted 6 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments the previous commit, where builtins that use add-patch infrastructure now respect diff.context and diff.interHunkContext file configurations.
Quoted 7 lines
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.
I skimmed the patch briefly. I am not sure if it is a good idea to
* add OPT_DIFF_*() macros to parse-options API, as its utility is very narrow, and forces those who are learning parse-options API to learn one more thing.
* validation of the value range to be duplicated for each and every users of the new OPT_DIFF_*() macros.
but other than that, looked reasonable to me.
Thanks.
Re: [PATCH v3 4/4] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetHi Leon
t/t3701-add-interactive.sh test_expect_success 'add -p rejects negative diff.context' ' · line 1257
Quoted 5 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
t/t3701-add-interactive.sh +3
-0+for cmd in add checkout restore 'commit -m file' +do + test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" "
Looking at this again, I think the test bodies here and below should be wrapped in single quotes because they are passed to eval and we want to expand $cmd when the body is evaluated, not before. That would also simplify the quoting inside the tests as we don't need to escape double quotes. That's not your fault - you've just copied what I suggested before.
t/t4055-diff-context.sh test_expect_success 'The -U option overrides diff.context' ' · line 65
Quoted 5 lines
t/t4055-diff-context.sh +5
-0+test_expect_success 'The -U option overrides diff.context for "add"' ' + test_config diff.context 8 && + git add -U4 -p >output && + test_grep ! "^ firstline" output +'
Don't the tests above check this as they set diff.context and diff.interhunkcontext and pass different values to -U and --inter-hunk-context?
Thanks
Phillip
Re: [PATCH v3 4/4] add-patch: add diff.context command line overrides
In reply to Junio C HamanoQuoted 13 lines · Junio C Hamano
Quoted 11 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
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.
Quoted 8 lines
Quoted 2 lines
This mimics commands such as diff and log, which allow for both context file configuration and command line overrides.
I skimmed the patch briefly. I am not sure if it is a good idea to
* add OPT_DIFF_*() macros to parse-options API, as its utility is very narrow, and forces those who are learning parse-options API to learn one more thing.
It means that we have consistent help for all the commands with these options which I think is valuable. We have a number of other macros that define options that are shared between commands and I think that works quite well.
Quoted 3 lines
* validation of the value range to be duplicated for each and every users of the new OPT_DIFF_*() macros.
Yes the validation is awkward. If we changed the OPT_DIFF_* to use a callback that rejected negative values that would reduce the duplication.
Quoted 1 line
but other than that, looked reasonable to me.
I've left a couple of comments on the tests but the code changes look reasonable to me too
Thanks
Phillip
Re: [PATCH v3 3/4] add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetHi Leon
Quoted 10 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations. This patch fixes this inconsistency.
This is because the plumbing commands used by "git add -p" to generate the diff do not read those config settings. Fix this by reading the config before generating the patch and passing it along to the diff command with the "-U" and "--inter-hunk-context" command-line options.
This looks good to me, thanks for working on it
Phillip
Quoted 112 lines
Signed-off-by Leon Michalak <[email protected]>--- add-interactive.c | 17 +++++++++++++++++ add-interactive.h | 1 + add-patch.c | 6 ++++++ t/t3701-add-interactive.sh | 22 ++++++++++++++++++++++ 4 files changed, 46 insertions(+)add-interactive.c +17
-0@@ -39,8 +39,12 @@ static void init_color(struct repository *r, struct add_i_state *s,void init_add_i_state (struct add_i_state *s,struct repository *r) {const char *value; +int context; +int interhunkcontext; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;@@ -78,6 +82,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &context)) { +if (context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +else + s->context = context; + } +if (!repo_config_get_int (r,"diff.interHunkContext" , &interhunkcontext)) { +if (interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +else + s->interhunkcontext = interhunkcontext; + } +repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL );add-interactive.h +1
-0@@ -18,6 +18,7 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; };void init_add_i_state (struct add_i_state *s,struct repository *r);add-patch.c +6
-0@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) {struct strvec args =STRVEC_INIT ;const char *diff_algorithm = s->s.interactive_diff_algorithm; +int diff_context = s->s.context; +int diff_interhunkcontext = s->s.interhunkcontext;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;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)int res;strvec_pushv (&args, s->mode->diff_cmd); +if (diff_context !=-1 ) +strvec_pushf (&args,"--unified=%i" , diff_context); +if (diff_interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , diff_interhunkcontext);if (diff_algorithm)strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm);if (s->revision) {t/t3701-add-interactive.sh +22
-0@@ -1230,4 +1230,26 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'add -p respects diff.context' ' + test_write_lines a b c d e f g h i j k l m >file && + git add file && + test_write_lines a b c d e f G h i j k l m >file && + echo y | git -c diff.context=5 add -p >actual && + test_grep "@@ -2,11 +2,11 @@" actual +' + +test_expect_success 'add -p respects diff.interHunkContext' ' + test_write_lines a b c d e f g h i j k l m n o p q r s >file && + git add file && + test_write_lines a b c d E f g i i j k l m N o p q r s >file && + echo y | git -c diff.interhunkcontext=2 add -p >actual && + test_grep "@@ -2,16 +2,16 @@" actual +' + +test_expect_success 'add -p rejects negative diff.context' ' + test_config diff.context -1 && + test_must_fail git add -p 2>output && + test_grep "diff.context cannot be negative" output +' + test_done
Re: [PATCH v3 4/4] add-patch: add diff.context command line overrides
In reply to Phillip WoodQuoted 8 lines · Phillip Wood
Quoted 3 lines
* add OPT_DIFF_*() macros to parse-options API, as its utility is very narrow, and forces those who are learning parse-options API to learn one more thing.
It means that we have consistent help for all the commands with these options which I think is valuable. We have a number of other macros that define options that are shared between commands and I think that works quite well.
I understand that principe. What I was wondering was if there are enough places to use these particular ones to make it worthwhile to enlarge the set of OPT_* macros.
Quoted 7 lines
Quoted 3 lines
* validation of the value range to be duplicated for each and
every
users of the new OPT_DIFF_*() macros.Yes the validation is awkward. If we changed the OPT_DIFF_* to use a callback that rejected negative values that would reduce the duplication.
Yeah, I was wondering about that approach, too. Another benefit with the "validate just after we parse the value before we assign the result to a variable or a struct member" approach is that we can also complain about -1 that is given from the command line (which the current code ignores, if I am not mistaken, because it needs to be silent if that -1 is there merely because it is the "not set yet" sentinel value).
Or perhaps the valid value range Réne has been workingon canbe used here?
Re: [PATCH v3 4/4] add-patch: add diff.context command line overrides
Quoted 6 lines · Junio C Hamano
Quoted 4 lines · Phillip Wood
Quoted 3 lines
* add OPT_DIFF_*() macros to parse-options API, as its utility is very narrow, and forces those who are learning parse-options API to learn one more thing.
Quoted 8 lines
Quoted 4 lines
It means that we have consistent help for all the commands with these options which I think is valuable. We have a number of other macros that define options that are shared between commands and I think that works quite well.
I understand that principe. What I was wondering was if there are enough places to use these particular ones to make it worthwhile to enlarge the set of OPT_* macros.
There are six users of each of these macros so I think it is worthwhile. That's two more users than there are for OPT_RERERE_AUTOUPDATE() and twice as many users as OPT_CONTAINS().
Quoted 16 lines
Quoted 7 lines
Quoted 3 lines
* validation of the value range to be duplicated for each and
every
users of the new OPT_DIFF_*() macros.Yes the validation is awkward. If we changed the OPT_DIFF_* to use a callback that rejected negative values that would reduce the duplication.
Yeah, I was wondering about that approach, too. Another benefit with the "validate just after we parse the value before we assign the result to a variable or a struct member" approach is that we can also complain about -1 that is given from the command line (which the current code ignores, if I am not mistaken, because it needs to be silent if that -1 is there merely because it is the "not set yet" sentinel value).
Quoted 2 lines
Or perhaps the valid value range Réne has been workingon canbe used here?
That would be nice
Thanks
Phillip
Re: [PATCH v3 4/4] add-patch: add diff.context command line overrides
Quoted 11 lines · Phillip Wood
Quoted 10 lines · Junio C Hamano
Quoted 8 lines · Phillip Wood
Quoted 3 lines
* add OPT_DIFF_*() macros to parse-options API, as its utility is very narrow, and forces those who are learning parse-options API to learn one more thing.
It means that we have consistent help for all the commands with these options which I think is valuable. We have a number of other macros that define options that are shared between commands and I think that works quite well.
Quoted 7 lines
Quoted 3 lines
I understand that principe. What I was wondering was if there are enough places to use these particular ones to make it worthwhile to enlarge the set of OPT_* macros.
There are six users of each of these macros so I think it is worthwhile. That's two more users than there are for
OPT_RERERE_AUTOUPDATE()and twice as many users asOPT_CONTAINS().
OK. Thanks.
Quoted 47 lines · Leon Michalak via GitGitGadget
This series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Changes since v1:
* Update commit descriptions
* Update tests to use the more modern and robusttest_grepandtest_configutils
* Reword some documentation / user messages
* Ensure each commit is atomic and builds/passes tests on it's own
* Make new command line options DRY
* Add tests for interhunk context interaction
* Error if context config/command line options are negative
* Drop previous last commit to do with new subcommand for --interactive add/commit. My motivations behind this patch series originally where quite simple, just for add-patch commands to respect context configs. This subcommand, after the discussion in v1, will require more thought and a larger implementation that what I had anticipated. I would prefer to leave this for another time as it's the least impactful but the most time intensive and complicated idea.
Quoted 5 lines
Changes since v2:
* Update tests to only test single command (following Philip's suggestion)
* Add negative option checks
* Minor commit re-wording
This iteration seems to have attracted a few review comments that are left ananswered. Will we see responses to them, and/or, a hopefully small and final update sometime soon?
Thanks.
I will respond to everything soon I hope, life has been in the way and I didn't anticipate so many comments :-)
Based on a skim read of the comments, the main thing I'm not sure I will be able to achieve is implementing the valid value range that a Rene has been working on as I don't have that context, but I'm not sure if this is a necessity to add?
Quoted 2 lines · Leon Michalak
I will respond to everything soon I hope, life has been in the way and I didn't anticipate so many comments :-)
Sure, no problem.
Historically, summer is a slower season and these messages I sent are primarily for me to keep track of topics on flight. "No, I am on vacation for a few more weeks" would have been perfectly fine response ;-).
Quoted 4 lines
Based on a skim read of the comments, the main thing I'm not sure I will be able to achieve is implementing the valid value range that a Rene has been working on as I don't have that context, but I'm not sure if this is a necessity to add?
v4 cover Better support for customising context lines in --patch commands
In reply to Leon Michalak via GitGitGadgetThis series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"
The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Changes since v1:
* Update commit descriptions
* Update tests to use the more modern and robust test_grep and test_config utils
* Reword some documentation / user messages
* Ensure each commit is atomic and builds/passes tests on it's own
* Make new command line options DRY
* Add tests for interhunk context interaction
* Error if context config/command line options are negative
* Drop previous last commit to do with new subcommand for --interactive add/commit. My motivations behind this patch series originally where quite simple, just for add-patch commands to respect context configs. This subcommand, after the discussion in v1, will require more thought and a larger implementation that what I had anticipated. I would prefer to leave this for another time as it's the least impactful but the most time intensive and complicated idea.
Changes since v2:
* Update tests to only test single command (following Philip's suggestion)
* Add negative option checks
* Minor commit re-wording
Changes since v3:
* Update commit descriptions
* Read struct properties directly instead of assigning to variables first
* Simplify config setting / error checking
* Remove redundant tests in later commit as they were replaced with better test(s)
* Change tests to use single quotes (this messes with the grep so was unable to explicitly test single quotes in the error messages, so decided to use regex . instead, which is what some other tests that have this problem seem to use as well)
Leon Michalak (4):
t: use test_grep in t3701 and t4055
t: use test_config in t4055
add-patch: respect diff.context configuration
add-patch: add diff.context command line overrides
Documentation/diff-context-options.adoc | 10 +++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 45 ++++++++++-- add-interactive.h | 17 ++++- add-patch.c | 14 ++-- builtin/add.c | 21 +++++- builtin/checkout.c | 31 +++++++- builtin/commit.c | 16 +++- builtin/reset.c | 17 ++++- builtin/stash.c | 56 +++++++++++--- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 97 +++++++++++++++++++------ t/t4055-diff-context.sh | 72 ++++++++++++------ t/t9902-completion.sh | 2 + 20 files changed, 332 insertions(+), 83 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
base-commit: cf6f63ea6bf35173e02e18bdc6a4ba41288acff9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1915%2FNinjaInShade%2Finteractive-patch-context-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1915/NinjaInShade/interactive-patch-context-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/1915
Range-diff vs v3:
1: 044a93014b6 ! 1: bbb2bc7082b test: use "test_grep"
@@ Metadata
Author: Leon Michalak <[email protected]>
## Commit message ##
- test: use "test_grep"
+ t: use test_grep in t3701 and t4055
- Use the modern "test_grep" test utility instead of regular "grep" which
- provides better debug information if tests fail.
-
- This is a prerequisite to the commits that follow which add to both test
- files.
+ As a preparatory clean-up, use the "test_grep" test utility instead of
+ regular "grep" which provides better debug information if tests fail.
2: e5c40d37750 ! 2: feace2d3676 test: use "test_config"
@@ Metadata
Author: Leon Michalak <[email protected]>
## Commit message ##
- test: use "test_config"
+ t: use test_config in t4055
Use the modern "test_config" test utility instead of manual"git config" as the former provides clean up on test completion.
3: 1ec8a138486 ! 3: 994029d6602 add-patch: respect diff.context configuration
@@ Commit message
Various builtins that use add-patch infrastructure do not respect
the user's diff.context and diff.interHunkContext file configurations.
- This patch fixes this inconsistency.
- This is because the plumbing commands used by "git add -p" to generate
- the diff do not read those config settings. Fix this by reading the
- config before generating the patch and passing it along to the diff
- command with the "-U" and "--inter-hunk-context" command-line options.
+ The user may be used to seeing their diffs with customized context size,
+ but not in the patches "git add -p" shows them to pick from.
+
+ Teach add-patch infrastructure to read these configuration variables and
+ pass their values when spawning the underlying plumbing commands as
+ their command line option.
Signed-off-by: Leon Michalak <[email protected]>
## add-interactive.c ##
-@@ add-interactive.c: static void init_color(struct repository *r, struct add_i_state *s,
- void init_add_i_state(struct add_i_state *s, struct repository *r)
- {
+@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repository *r)
const char *value;
-+ int context;
-+ int interhunkcontext;
s->r = r;
+ s->context = -1;
@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repositor
repo_config_get_string(r, "diff.algorithm",
&s->interactive_diff_algorithm);
-+ if (!repo_config_get_int(r, "diff.context", &context)) {
-+ if (context < 0)
++ if (!repo_config_get_int(r, "diff.context", &s->context))
++ if (s->context < 0)
+ die(_("%s cannot be negative"), "diff.context");
-+ else
-+ s->context = context;
-+ }
-+ if (!repo_config_get_int(r, "diff.interHunkContext", &interhunkcontext)) {
-+ if (interhunkcontext < 0)
++ if (!repo_config_get_int(r, "diff.interHunkContext", &s->interhunkcontext))
++ if (s->interhunkcontext < 0)
+ die(_("%s cannot be negative"), "diff.interHunkContext");
-+ else
-+ s->interhunkcontext = interhunkcontext;
-+ }
+
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
if (s->use_single_key)
@@ add-interactive.h: struct add_i_state {
void init_add_i_state(struct add_i_state *s, struct repository *r);
## add-patch.c ##
-@@ add-patch.c: static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
+@@ add-patch.c: static int normalize_marker(const char *p)
+ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
{
struct strvec args = STRVEC_INIT;
- const char *diff_algorithm = s->s.interactive_diff_algorithm;
-+ int diff_context = s->s.context;
-+ int diff_interhunkcontext = s->s.interhunkcontext;
+- const char *diff_algorithm = s->s.interactive_diff_algorithm;
struct strbuf *plain = &s->plain, *colored = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
char *p, *pend, *colored_p = NULL, *colored_pend = NULL, marker = '\0';
@@ add-patch.c: static int parse_diff(struct add_p_state *s, const struct pathspec
int res;
strvec_pushv(&args, s->mode->diff_cmd);
-+ if (diff_context != -1)
-+ strvec_pushf(&args, "--unified=%i", diff_context);
-+ if (diff_interhunkcontext != -1)
-+ strvec_pushf(&args, "--inter-hunk-context=%i", diff_interhunkcontext);
- if (diff_algorithm)
- strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
+- if (diff_algorithm)
+- strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
++ if (s->s.context != -1)
++ strvec_pushf(&args, "--unified=%i", s->s.context);
++ if (s->s.interhunkcontext != -1)
++ strvec_pushf(&args, "--inter-hunk-context=%i", s->s.interhunkcontext);
++ if (s->s.interactive_diff_algorithm)
++ strvec_pushf(&args, "--diff-algorithm=%s", s->s.interactive_diff_algorithm);
if (s->revision) {
+ struct object_id oid;
+ strvec_push(&args,
## t/t3701-add-interactive.sh ##
@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' '
4: b68c58b667c ! 4: 2774b930406 add-patch: add diff.context command line overrides
@@ add-interactive.c: static void init_color(struct repository *r, struct add_i_sta
+ struct add_p_opt *add_p_opt)
{
const char *value;
- int context;
+
@@ add-interactive.c: void init_add_i_state(struct add_i_state *s, struct repository *r)
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
if (s->use_single_key)
@@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *
OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
## t/t3701-add-interactive.sh ##
-@@ t/t3701-add-interactive.sh: test_expect_success 'add -p rejects negative diff.context' '
- test_grep "diff.context cannot be negative" output
+@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' '
+ test_cmp expect actual
'
+-test_expect_success 'add -p respects diff.context' '
+- test_write_lines a b c d e f g h i j k l m >file &&
+for cmd in add checkout restore 'commit -m file'
+do
-+ test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" "
++ test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" '
+ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
+ git add file &&
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ $cmd -p -U 4 --inter-hunk-context 2 >actual &&
-+ test_grep \"@@ -2,20 +2,20 @@\" actual
-+ "
++ test_grep "@@ -2,20 +2,20 @@" actual
++ '
+done
+
+test_expect_success 'reset accepts -U and --inter-hunk-context' '
+ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
+ git commit -m file file &&
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
-+ git add file &&
+ git add file &&
+- test_write_lines a b c d e f G h i j k l m >file &&
+- echo y | git -c diff.context=5 add -p >actual &&
+- test_grep "@@ -2,11 +2,11 @@" actual
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ reset -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
-+'
-+
+ '
+
+-test_expect_success 'add -p respects diff.interHunkContext' '
+- test_write_lines a b c d e f g h i j k l m n o p q r s >file &&
+- git add file &&
+- test_write_lines a b c d E f g i i j k l m N o p q r s >file &&
+- echo y | git -c diff.interhunkcontext=2 add -p >actual &&
+- test_grep "@@ -2,16 +2,16 @@" actual
+test_expect_success 'stash accepts -U and --inter-hunk-context' '
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
+ git commit -m file file &&
@@ t/t3701-add-interactive.sh: test_expect_success 'add -p rejects negative diff.co
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ stash -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
-+'
-+
-+for cmd in add checkout commit reset restore 'stash save' 'stash push'
+ '
+
+-test_expect_success 'add -p rejects negative diff.context' '
+- test_config diff.context -1 &&
+- test_must_fail git add -p 2>output &&
+- test_grep "diff.context cannot be negative" output
+-'
++for cmd in add checkout commit reset restore "stash save" "stash push"
+do
-+ test_expect_success "$cmd rejects invalid context options" "
++ test_expect_success "$cmd rejects invalid context options" '
+ test_must_fail git $cmd -p -U -3 2>actual &&
+ cat actual | echo &&
-+ test_grep -e \"'--unified' cannot be negative\" actual &&
++ test_grep -e ".--unified. cannot be negative" actual &&
+
+ test_must_fail git $cmd -p --inter-hunk-context -3 2>actual &&
-+ test_grep -e \"'--inter-hunk-context' cannot be negative\" actual &&
++ test_grep -e ".--inter-hunk-context. cannot be negative" actual &&
+
+ test_must_fail git $cmd -U 7 2>actual &&
-+ test_grep -E \"'--unified' requires '(--interactive/)?--patch'\" actual &&
++ test_grep -E ".--unified. requires .(--interactive/)?--patch." actual &&
+
+ test_must_fail git $cmd --inter-hunk-context 2 2>actual &&
-+ test_grep -E \"'--inter-hunk-context' requires '(--interactive/)?--patch'\" actual
-+ "
++ test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual
++ '
+done
-+
+
test_done
## t/t4055-diff-context.sh ##Signature · 1 line
gitgitgadget
PATCH v4 1/4 t: use test_grep in t3701 and t4055
From: Leon Michalak <[email protected]>
As a preparatory clean-up, use the "test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.
--- t/t3701-add-interactive.sh | 48 +++++++++++++++++++------------------- t/t4055-diff-context.sh | 28 +++++++++++----------- 2 files changed, 38 insertions(+), 38 deletions(-)
t/t3701-add-interactive.sh +24 -24
@@ -63,7 +63,7 @@ test_expect_success 'setup (initial)' ' ' test_expect_success 'status works (initial)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'setup expected' '
@@ -86,7 +86,7 @@ test_expect_success 'revert works (initial)' ' git add file && test_write_lines r 1 | git add -i && git ls-files >output && - ! grep . output + test_grep ! . output ' test_expect_success 'add untracked (multiple)' '
@@ -109,7 +109,7 @@ test_expect_success 'setup (commit)' ' ' test_expect_success 'status works (commit)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'update can stage deletions' '
@@ -141,7 +141,7 @@ test_expect_success 'revert works (commit)' ' git add file && test_write_lines r 1 | git add -i && git add -i </dev/null >output && - grep "unchanged *+3/-0 file" output + test_grep "unchanged *+3/-0 file" output ' test_expect_success 'reject multi-key input' '
@@ -185,7 +185,7 @@ test_expect_success 'setup fake editor' ' test_expect_success 'bad edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -198,7 +198,7 @@ test_expect_success 'setup patch' ' test_expect_success 'garbage edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -313,8 +313,8 @@ test_expect_success FILEMODE 'stage mode and hunk' ' chmod +x file && printf "y\\ny\\n" | git add -p && git diff --cached file >out && - grep "new mode" out && - grep "+content" out && + test_grep "new mode" out && + test_grep "+content" out && git diff file >out && test_must_be_empty out '
@@ -636,7 +636,7 @@ test_expect_success 'split hunk "add -p (edit)"' ' printf "%s\n" s e q n q q | EDITOR=: git add -p && git diff >actual && - ! grep "^+15" actual + test_grep ! "^+15" actual ' test_expect_success 'split hunk "add -p (no, yes, edit)"' '
@@ -648,7 +648,7 @@ test_expect_success 'split hunk "add -p (no, yes, edit)"' ' EDITOR=: git add -p 2>error && test_must_be_empty error && git diff >actual && - ! grep "^+31" actual + test_grep ! "^+31" actual ' test_expect_success 'split hunk with incomplete line at end' '
@@ -682,7 +682,7 @@ test_expect_success 'edit, adding lines to the first hunk' ' EDITOR=./fake_editor.sh git add -p 2>error && test_must_be_empty error && git diff --cached >actual && - grep "^+22" actual + test_grep "^+22" actual ' test_expect_success 'patch mode ignores unmerged entries' '
@@ -696,7 +696,7 @@ test_expect_success 'patch mode ignores unmerged entries' ' test_must_fail git merge side && echo changed >non-conflict.t && echo y | git add -p >output && - ! grep a/conflict.t output && + test_grep ! a/conflict.t output && cat >expected <<-\EOF && * Unmerged path conflict.t diff --git a/non-conflict.t b/non-conflict.t
@@ -728,7 +728,7 @@ test_expect_success 'diffs can be colorized' ' # We do not want to depend on the exact coloring scheme # git uses for diffs, so just check that we saw some kind of color. - grep "$(printf "\\033")" output + test_grep "$(printf "\\033")" output ' test_expect_success 'colors can be overridden' '
@@ -743,7 +743,7 @@ test_expect_success 'colors can be overridden' ' -c color.interactive.error=blue \ add -i 2>err.raw <input && test_decode_color <err.raw >err && - grep "<BLUE>Huh (trigger)?<RESET>" err && + test_grep "<BLUE>Huh (trigger)?<RESET>" err && test_write_lines help quit >input && force_color git \
@@ -863,7 +863,7 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' printf y >y && force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y && test_decode_color <output.raw >output && - grep "old<" output + test_grep "old<" output ' test_expect_success 'diffFilter filters diff' '
@@ -876,7 +876,7 @@ test_expect_success 'diffFilter filters diff' ' # avoid depending on the exact coloring or content of the prompts, # and just make sure we saw our diff prefixed - grep foo:.*content output + test_grep foo:.*content output ' test_expect_success 'detect bogus diffFilter output' '
@@ -886,7 +886,7 @@ test_expect_success 'detect bogus diffFilter output' ' test_config interactive.diffFilter "sed 6d" && printf y >y && force_color test_must_fail git add -p <y >output 2>&1 && - grep "mismatched output" output + test_grep "mismatched output" output ' test_expect_success 'handle iffy colored hunk headers' '
@@ -896,7 +896,7 @@ test_expect_success 'handle iffy colored hunk headers' ' printf n >n && force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \ add -p >output 2>&1 <n && - grep "^XX$" output + test_grep "^XX$" output ' test_expect_success 'handle very large filtered diff' '
@@ -1002,7 +1002,7 @@ test_expect_success 'add -p does not expand argument lists' ' # update it, but we want to be sure that our "." pathspec # was not expanded into the argument list of any command. # So look only for "not-changed". - ! grep -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out + test_grep ! -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out ' test_expect_success 'hunk-editing handles custom comment char' '
@@ -1072,21 +1072,21 @@ test_expect_success 'setup different kinds of dirty submodules' ' test_expect_success 'status ignores dirty submodules (except HEAD)' ' git -C for-submodules add -i </dev/null >output && - grep dirty-head output && - grep dirty-both-ways output && - ! grep dirty-otherwise output + test_grep dirty-head output && + test_grep dirty-both-ways output && + test_grep ! dirty-otherwise output ' test_expect_success 'handle submodules' ' echo 123 >>for-submodules/dirty-otherwise/initial.t && force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 && - grep "No changes" output && + test_grep "No changes" output && force_color git -C for-submodules add -p dirty-head >output 2>&1 <y && git -C for-submodules ls-files --stage dirty-head >actual && rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" && - grep "$rev" actual + test_grep "$rev" actual ' test_expect_success 'set up pathological context' '
t/t4055-diff-context.sh +14 -14
@@ -38,36 +38,36 @@ test_expect_success 'setup' ' test_expect_success 'the default number of context lines is 3' ' git diff >output && - ! grep "^ d" output && - grep "^ e" output && - grep "^ j" output && - ! grep "^ k" output + test_grep ! "^ d" output && + test_grep "^ e" output && + test_grep "^ j" output && + test_grep ! "^ k" output ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && - ! grep firstline output && + test_grep ! firstline output && git config diff.context 8 && git log -1 -p >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' git config diff.context 8 && git log -U4 -1 >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' git config diff.context 8 && git diff >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' git config diff.context 8 && git diff-files -p >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' '
@@ -85,8 +85,8 @@ test_expect_success 'negative integer config parsing' ' test_expect_success '-U0 is valid, so is diff.context=0' ' git config diff.context 0 && git diff >output && - grep "^-ADDED" output && - grep "^+MODIFIED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output ' test_expect_success '-U2147483647 works' '
@@ -94,9 +94,9 @@ test_expect_success '-U2147483647 works' ' test_line_count = 16 x && git diff -U2147483647 >output && test_line_count = 22 output && - grep "^-ADDED" output && - grep "^+MODIFIED" output && - grep "^+APPENDED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output && + test_grep "^+APPENDED" output ' test_done
Signature · 1 line
gitgitgadget
PATCH v4 2/4 t: use test_config in t4055
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Use the modern "test_config" test utility instead of manual"git config" as the former provides clean up on test completion.
This is a prerequisite to the commits that follow which add to this test file.
--- t/t4055-diff-context.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
t/t4055-diff-context.sh +7 -7
@@ -47,43 +47,43 @@ test_expect_success 'the default number of context lines is 3' ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && test_grep ! firstline output && - git config diff.context 8 && + test_config diff.context 8 && git log -1 -p >output && test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' - git config diff.context 8 && + test_config diff.context 8 && git log -U4 -1 >output && test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' - git config diff.context 8 && + test_config diff.context 8 && git diff >output && test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' - git config diff.context 8 && + test_config diff.context 8 && git diff-files -p >output && test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' ' - git config diff.context no && + test_config diff.context no && test_must_fail git diff 2>output && test_grep "bad numeric config value" output ' test_expect_success 'negative integer config parsing' ' - git config diff.context -1 && + test_config diff.context -1 && test_must_fail git diff 2>output && test_grep "bad config variable" output ' test_expect_success '-U0 is valid, so is diff.context=0' ' - git config diff.context 0 && + test_config diff.context 0 && git diff >output && test_grep "^-ADDED" output && test_grep "^+MODIFIED" output
Signature · 1 line
gitgitgadget
PATCH v4 3/4 add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations.
The user may be used to seeing their diffs with customized context size, but not in the patches "git add -p" shows them to pick from.
Teach add-patch infrastructure to read these configuration variables and pass their values when spawning the underlying plumbing commands as their command line option.
--- add-interactive.c | 9 +++++++++ add-interactive.h | 1 + add-patch.c | 9 ++++++--- t/t3701-add-interactive.sh | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-)
add-interactive.c +9 -0
@@ -41,6 +41,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)const char *value; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;
@@ -78,6 +80,13 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &s->context)) +if (s->context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +if (!repo_config_get_int (r,"diff.interHunkContext" , &s->interhunkcontext)) +if (s->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL );
add-interactive.h +1 -0
@@ -18,6 +18,7 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; };void init_add_i_state (struct add_i_state *s,struct repository *r);
add-patch.c +6 -3
@@ -414,7 +414,6 @@ static int normalize_marker(const char *p)static int parse_diff (struct add_p_state *s,const struct pathspec *ps) {struct strvec args =STRVEC_INIT ; -const char *diff_algorithm = s->s.interactive_diff_algorithm;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;char *p, *pend, *colored_p =NULL , *colored_pend =NULL , marker ='\0' ;
@@ -424,8 +423,12 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)int res;strvec_pushv (&args, s->mode->diff_cmd); -if (diff_algorithm) -strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm); +if (s->s.context !=-1 ) +strvec_pushf (&args,"--unified=%i" , s->s.context); +if (s->s.interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , s->s.interhunkcontext); +if (s->s.interactive_diff_algorithm) +strvec_pushf (&args,"--diff-algorithm=%s" , s->s.interactive_diff_algorithm);if (s->revision) {struct object_id oid; strvec_push(&args,
t/t3701-add-interactive.sh +22 -0
@@ -1230,4 +1230,26 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'add -p respects diff.context' ' + test_write_lines a b c d e f g h i j k l m >file && + git add file && + test_write_lines a b c d e f G h i j k l m >file && + echo y | git -c diff.context=5 add -p >actual && + test_grep "@@ -2,11 +2,11 @@" actual +' + +test_expect_success 'add -p respects diff.interHunkContext' ' + test_write_lines a b c d e f g h i j k l m n o p q r s >file && + git add file && + test_write_lines a b c d E f g i i j k l m N o p q r s >file && + echo y | git -c diff.interhunkcontext=2 add -p >actual && + test_grep "@@ -2,16 +2,16 @@" actual +' + +test_expect_success 'add -p rejects negative diff.context' ' + test_config diff.context -1 && + test_must_fail git add -p 2>output && + test_grep "diff.context cannot be negative" output +' + test_done
Signature · 1 line
gitgitgadget
PATCH v4 4/4 add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
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.
--- Documentation/diff-context-options.adoc | 10 +++++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 36 +++++++++++---- add-interactive.h | 16 +++++-- add-patch.c | 5 ++- builtin/add.c | 21 +++++++-- builtin/checkout.c | 31 +++++++++++-- builtin/commit.c | 16 ++++++- builtin/reset.c | 17 ++++++- builtin/stash.c | 56 ++++++++++++++++++----- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 59 ++++++++++++++++++------- t/t4055-diff-context.sh | 30 +++++++++++++ t/t9902-completion.sh | 2 + 20 files changed, 265 insertions(+), 51 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
Documentation/diff-context-options.adoc new file +10 -0
@@ -0,0 +1,10 @@ +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset.
Documentation/git-add.adoc +2 -0
@@ -104,6 +104,8 @@ This effectively runs `add --interactive`, but bypasses the initial command menu and directly jumps to the `patch` subcommand. See ``Interactive mode'' for details. +include::diff-context-options.adoc[] + `-e`:: `--edit`:: Open the diff vs. the index in an editor and let the user
Documentation/git-checkout.adoc +2 -0
@@ -289,6 +289,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. +include::diff-context-options.adoc[] + `--ignore-other-worktrees`:: `git checkout` refuses when the wanted branch is already checked out or otherwise in use by another worktree. This option makes
Documentation/git-commit.adoc +2 -0
@@ -76,6 +76,8 @@ OPTIONS which changes to commit. See linkgit:git-add[1] for details. +include::diff-context-options.adoc[] + `-C <commit>`:: `--reuse-message=<commit>`:: Take an existing _<commit>_ object, and reuse the log message
Documentation/git-reset.adoc +2 -0
@@ -125,6 +125,8 @@ OPTIONS separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). +include::diff-context-options.adoc[] + `--`:: Do not interpret any more arguments as options.
Documentation/git-restore.adoc +2 -0
@@ -52,6 +52,8 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. +include::diff-context-options.adoc[] + `-W`:: `--worktree`:: `-S`::
Documentation/git-stash.adoc +2 -0
@@ -208,6 +208,8 @@ to learn how to operate the `--patch` mode. The `--patch` option implies `--keep-index`. You can use `--no-keep-index` to override this. +include::diff-context-options.adoc[] + -S:: --staged:: This option is only valid for `push` and `save` commands.
add-interactive.c +28 -8
@@ -36,7 +36,8 @@ static void init_color(struct repository *r, struct add_i_state *s,free (key); } -void init_add_i_state (struct add_i_state *s,struct repository *r) +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt) {const char *value;
@@ -90,6 +91,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); + +if (add_p_opt->context !=-1 ) { +if (add_p_opt->context <0 ) +die (_ ("%s cannot be negative" ),"--unified" ); + s->context = add_p_opt->context; + } +if (add_p_opt->interhunkcontext !=-1 ) { +if (add_p_opt->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"--inter-hunk-context" ); + s->interhunkcontext = add_p_opt->interhunkcontext; + } }void clear_add_i_state (struct add_i_state *s)
@@ -978,6 +990,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps, opts->prompt =N_ ("Patch update" ); count =list_and_choose (s, files, opts);if (count >0 ) { +struct add_p_opt add_p_opt = { + .context = s->context, + .interhunkcontext = s->interhunkcontext, + };struct strvec args =STRVEC_INIT ;struct pathspec ps_selected = {0 };
@@ -988,7 +1004,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,parse_pathspec (&ps_selected,PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL ,PATHSPEC_LITERAL_PATH ,"" , args.v); - res =run_add_p (s->r,ADD_P_ADD ,NULL , &ps_selected); + res =run_add_p (s->r,ADD_P_ADD , &add_p_opt,NULL , &ps_selected);strvec_clear (&args);clear_pathspec (&ps_selected); }
@@ -1023,10 +1039,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; -strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" , -oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), -"--" ,NULL ); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );for (i =0 ; i < files->items.nr; i++)if (files->selected[i]) strvec_push(&cmd.args,
@@ -1119,7 +1138,8 @@ static void command_prompt_help(struct add_i_state *s) _("(empty) select nothing")); } -int run_add_i (struct repository *r,const struct pathspec *ps) +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt) {struct add_i_state s = {NULL };struct print_command_item_data data = {"[" ,"]" };
@@ -1162,7 +1182,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps) ->util = util; } -init_add_i_state (&s, r); +init_add_i_state (&s, r, add_p_opt);/* * When color was asked for, use the prompt color for
add-interactive.h +13 -3
@@ -3,6 +3,13 @@#include "color.h" +struct add_p_opt { +int context; +int interhunkcontext; +}; + +#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 } +struct add_i_state {struct repository *r;int use_color;
@@ -21,12 +28,14 @@ struct add_i_state {int context, interhunkcontext; }; -void init_add_i_state (struct add_i_state *s,struct repository *r); +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt);void clear_add_i_state (struct add_i_state *s);struct repository ;struct pathspec ; -int run_add_i (struct repository *r,const struct pathspec *ps); +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt);enum add_p_mode {ADD_P_ADD ,
@@ -37,6 +46,7 @@ enum add_p_mode { };int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps); +struct add_p_opt *o,const char *revision, +const struct pathspec *ps);#endif
add-patch.c +3 -2
@@ -1763,14 +1763,15 @@ soft_increment: }int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps) +struct add_p_opt *o,const char *revision, +const struct pathspec *ps) {struct add_p_state s = { { r },STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT };size_t i, binary_count =0 ; -init_add_i_state (&s.s, r); +init_add_i_state (&s.s, r, o);if (mode ==ADD_P_STASH ) s.mode = &patch_mode_stash;
builtin/add.c +17 -4
@@ -29,6 +29,7 @@ static const char * const builtin_add_usage[] = { NULL };static int patch_interactive, add_interactive, edit_interactive; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int take_worktree_changes;static int add_renormalize;static int pathspec_file_nul;
@@ -157,7 +158,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch) +int patch,struct add_p_opt *add_p_opt) {struct pathspec pathspec;int ret;
@@ -169,9 +170,9 @@ int interactive_add(struct repository *repo, prefix, argv);if (patch) - ret = !!run_add_p (repo,ADD_P_ADD ,NULL , &pathspec); + ret = !!run_add_p (repo,ADD_P_ADD , add_p_opt,NULL , &pathspec);else - ret = !!run_add_i (repo, &pathspec); + ret = !!run_add_i (repo, &pathspec, add_p_opt);clear_pathspec (&pathspec);return ret;
@@ -253,6 +254,8 @@ static struct option builtin_add_options[] = {OPT_GROUP ("" ),OPT_BOOL ('i' ,"interactive" , &add_interactive,N_ ("interactive picking" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('e' ,"edit" , &edit_interactive,N_ ("edit current diff and apply" )),OPT__FORCE (&ignored_too,N_ ("allow adding otherwise ignored files" ),0 ), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -394,6 +397,11 @@ int cmd_add(int argc,prepare_repo_settings (repo); repo->settings.command_requires_full_index =0 ; +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +if (patch_interactive) add_interactive =1 ;if (add_interactive) {
@@ -401,7 +409,12 @@ int cmd_add(int argc,die (_ ("options '%s' and '%s' cannot be used together" ),"--dry-run" ,"--interactive/--patch" );if (pathspec_from_file)die (_ ("options '%s' and '%s' cannot be used together" ),"--pathspec-from-file" ,"--interactive/--patch" ); -exit (interactive_add (repo, argv +1 , prefix, patch_interactive)); +exit (interactive_add (repo, argv +1 , prefix, patch_interactive, &add_p_opt)); + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }if (edit_interactive) {
builtin/checkout.c +28 -3
@@ -61,6 +61,8 @@ static const char * const restore_usage[] = {struct checkout_opts {int patch_mode; +int patch_context; +int patch_interhunk_context;int quiet;int merge;int force;
@@ -104,7 +106,12 @@ struct checkout_opts {struct tree *source_tree; }; -#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 } +#define CHECKOUT_OPTS_INIT { \ + .conflict_style = -1, \ + .merge = -1, \ + .patch_context = -1, \ + .patch_interhunk_context = -1, \ +}struct branch_info {char *name;/* The short name used */
@@ -539,6 +546,10 @@ static int checkout_paths(const struct checkout_opts *opts,if (opts->patch_mode) {enum add_p_mode patch_mode; +struct add_p_opt add_p_opt = { + .context = opts->patch_context, + .interhunkcontext = opts->patch_interhunk_context, + };const char *rev = new_branch_info->name;char rev_oid[GIT_MAX_HEXSZ +1 ];
@@ -564,8 +575,8 @@ static int checkout_paths(const struct checkout_opts *opts,else BUG ("either flag must have been set, worktree=%d, index=%d" , opts->checkout_worktree, opts->checkout_index); -return !!run_add_p (the_repository, patch_mode, rev, - &opts->pathspec); +return !!run_add_p (the_repository, patch_mode, &add_p_opt, + rev, &opts->pathspec); }repo_hold_locked_index (the_repository, &lock_file,LOCK_DIE_ON_ERROR );
@@ -1738,6 +1749,8 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts, N_("checkout their version for unmerged files"), 3, PARSE_OPT_NONEG),OPT_BOOL ('p' ,"patch" , &opts->patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&opts->patch_context), +OPT_DIFF_INTERHUNK_CONTEXT (&opts->patch_interhunk_context),OPT_BOOL (0 ,"ignore-skip-worktree-bits" , &opts->ignore_skipworktree,N_ ("do not limit pathspecs to sparse entries only" )), OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
@@ -1780,6 +1793,18 @@ static int checkout_main(int argc, const char **argv, const char *prefix, argc =parse_options (argc, argv, prefix, options, usagestr, parseopt_flags); +if (opts->patch_context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (opts->patch_interhunk_context <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); + +if (!opts->patch_mode) { +if (opts->patch_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (opts->patch_interhunk_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); + } +if (opts->show_progress <0 ) {if (opts->quiet) opts->show_progress =0 ;
builtin/commit.c +15 -1
@@ -19,6 +19,7 @@#include "environment.h" #include "diff.h" #include "commit.h" +#include "add-interactive.h" #include "gettext.h" #include "revision.h" #include "wt-status.h"
@@ -122,6 +123,7 @@ static const char *edit_message, *use_message;static char *fixup_message, *fixup_commit, *squash_message;static const char *fixup_prefix;static int all, also, interactive, patch_interactive, only, amend, signoff; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int edit_flag =-1 ;/* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */
@@ -354,6 +356,11 @@ static const char *prepare_index(const char **argv, const char *prefix,const char *ret;char *path =NULL ; +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +if (is_status) refresh_flags |=REFRESH_UNMERGED ; parse_pathspec(&pathspec, 0,
@@ -400,7 +407,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env =xstrdup_or_null (getenv (INDEX_ENVIRONMENT ));setenv (INDEX_ENVIRONMENT , the_repository->index_file,1 ); -if (interactive_add (the_repository, argv, prefix, patch_interactive) !=0 ) +if (interactive_add (the_repository, argv, prefix, patch_interactive, &add_p_opt) !=0 )die (_ ("interactive add failed" )); the_repository->index_file = old_repo_index_file;
@@ -424,6 +431,11 @@ static const char *prepare_index(const char **argv, const char *prefix, commit_style =COMMIT_NORMAL ; ret =get_lock_file_path (&index_lock); goto out; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }/*
@@ -1722,6 +1734,8 @@ int cmd_commit(int argc,OPT_BOOL ('i' ,"include" , &also,N_ ("add specified files to index for commit" )),OPT_BOOL (0 ,"interactive" , &interactive,N_ ("interactively add files" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("interactively add changes" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('o' ,"only" , &only,N_ ("commit only specified files" )),OPT_BOOL ('n' ,"no-verify" , &no_verify,N_ ("bypass pre-commit and commit-msg hooks" )), OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
builtin/reset.c +15 -2
@@ -346,6 +346,7 @@ int cmd_reset(int argc,struct object_id oid;struct pathspec pathspec;int intent_to_add =0 ; +struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;const struct option options[] = {OPT__QUIET (&quiet,N_ ("be quiet, only report errors" )), OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -370,6 +371,8 @@ int cmd_reset(int argc, PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),OPT_BOOL ('p' ,"patch" , &patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('N' ,"intent-to-add" , &intent_to_add,N_ ("record only the fact that removed paths will be added later" )), OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -420,6 +423,11 @@ int cmd_reset(int argc,oidcpy (&oid, &tree->object.oid); } +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +prepare_repo_settings (the_repository); the_repository->settings.command_requires_full_index =0 ;
@@ -427,9 +435,14 @@ int cmd_reset(int argc,if (reset_type !=NONE )die (_ ("options '%s' and '%s' cannot be used together" ),"--patch" ,"--{hard,mixed,soft}" );trace2_cmd_mode ("patch-interactive" ); - update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , rev, - &pathspec); + update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , + &add_p_opt, rev, &pathspec); goto cleanup; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }/* git reset tree [--] paths... can be used to
builtin/stash.c +45 -11
136 lines not on this page · raw message
commit.h +2 -1
@@ -2,6 +2,7 @@#define COMMIT_H #include "object.h" +#include "add-interactive.h" struct signature_check ;struct strbuf ;
@@ -257,7 +258,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch); +int patch,struct add_p_opt *add_p_opt);struct commit_extra_header {struct commit_extra_header *next;
parse-options.h +2 -0
@@ -616,6 +616,8 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);#define OPT_PATHSPEC_FROM_FILE (v) OPT_FILENAME(0, "pathspec-from-file", v, N_("read pathspec from file"))#define OPT_PATHSPEC_FILE_NUL (v) OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))#define OPT_AUTOSTASH (v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after")) +#define OPT_DIFF_UNIFIED (v) OPT_INTEGER_F('U', "unified", v, N_("generate diffs with <n> lines context"), PARSE_OPT_NONEG) +#define OPT_DIFF_INTERHUNK_CONTEXT (v) OPT_INTEGER_F(0, "inter-hunk-context", v, N_("show context between diff hunks up to the specified number of lines"), PARSE_OPT_NONEG)#define OPT_IPVERSION (v) \ OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
t/t3701-add-interactive.sh +43 -16
69 lines not on this page · raw message
t/t4055-diff-context.sh +30 -0
@@ -58,6 +58,36 @@ test_expect_success 'The -U option overrides diff.context' ' test_grep ! "^ firstline" output ' +test_expect_success 'The -U option overrides diff.context for "add"' ' + test_config diff.context 8 && + git add -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "commit"' ' + test_config diff.context 8 && + ! git commit -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "checkout"' ' + test_config diff.context 8 && + git checkout -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "stash"' ' + test_config diff.context 8 && + ! git stash -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "restore"' ' + test_config diff.context 8 && + git restore -U4 -p >output && + test_grep ! "^ firstline" output +' + test_expect_success 'diff.context honored by "diff"' ' test_config diff.context 8 && git diff >output &&
t/t9902-completion.sh +2 -0
@@ -2596,6 +2596,8 @@ test_expect_success 'double dash "git checkout"' ' --merge Z --conflict=Z --patch Z + --unified=Z + --inter-hunk-context=Z --ignore-skip-worktree-bits Z --ignore-other-worktrees Z --recurse-submodules Z
Signature · 1 line
gitgitgadget
Quoted 11 lines · Leon Michalak via GitGitGadget
Changes since v3:
* Update commit descriptions
* Read struct properties directly instead of assigning to variables first
* Simplify config setting / error checking
* Remove redundant tests in later commit as they were replaced with better test(s)
* Change tests to use single quotes (this messes with the grep so was unable to explicitly test single quotes in the error messages, so decided to use regex . instead, which is what some other tests that have this problem seem to use as well)
All of the above looked reasonably well done. Will replace.
Unless there are objections, let me mark the topic for 'next' soonish.
Thanks.
Re: [PATCH v4 4/4] add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetHi Leon
Quoted 6 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments the previous commit, where builtins that use add-patch infrastructure now respect diff.context and diff.interHunkContext file configurations.
Quoted 7 lines
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.
Thanks for updating the quoting in the tests. Unfortunately this patch now deletes the tests added in the last commit which I don't think is correct.
t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1234
Quoted 3 lines
t/t3701-add-interactive.sh +0
-2-test_expect_success 'add -p respects diff.context' ' - test_write_lines a b c d e f g h i j k l m >file &&
I think there is some confusion here - why are we deleting the tests added in the last commit? This removes the test coverage for diff.context and diff.interHunkContext
Quoted 21 lines
t/t3701-add-interactive.sh +17
-3+for cmd in add checkout restore 'commit -m file' +do + test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" ' + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && + git add file && + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && + echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ + $cmd -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual + ' +done + +test_expect_success 'reset accepts -U and --inter-hunk-context' ' + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && + git commit -m file file && + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && git add file && - test_write_lines a b c d e f G h i j k l m >file && - echo y | git -c diff.context=5 add -p >actual && - test_grep "@@ -2,11 +2,11 @@" actual + echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1246
Quoted 10 lines
t/t3701-add-interactive.sh +2
-6+ reset -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual ' -test_expect_success 'add -p respects diff.interHunkContext' ' - test_write_lines a b c d e f g h i j k l m n o p q r s >file && - git add file && - test_write_lines a b c d E f g i i j k l m N o p q r s >file && - echo y | git -c diff.interhunkcontext=2 add -p >actual && - test_grep "@@ -2,16 +2,16 @@" actual
This is also deleting a test added in the last patch
Quoted 4 lines
t/t3701-add-interactive.sh +4
-0+test_expect_success 'stash accepts -U and --inter-hunk-context' ' + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && + git commit -m file file && + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1253
Quoted 10 lines
t/t3701-add-interactive.sh +3
-5+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ + stash -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual ' -test_expect_success 'add -p rejects negative diff.context' ' - test_config diff.context -1 && - test_must_fail git add -p 2>output && - test_grep "diff.context cannot be negative" output -'
and so is this. The tests you're adding look good but we shouldn't be deleting the existing ones.
Quoted 7 lines
t/t3701-add-interactive.sh +7
-0+for cmd in add checkout commit reset restore "stash save" "stash push" +do + test_expect_success "$cmd rejects invalid context options" ' + test_must_fail git $cmd -p -U -3 2>actual && + cat actual | echo && + test_grep -e ".--unified. cannot be negative" actual && +
t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1280
Quoted 10 lines
t/t3701-add-interactive.sh +10
-0+ test_must_fail git $cmd -p --inter-hunk-context -3 2>actual && + test_grep -e ".--inter-hunk-context. cannot be negative" actual && + + test_must_fail git $cmd -U 7 2>actual && + test_grep -E ".--unified. requires .(--interactive/)?--patch." actual && + + test_must_fail git $cmd --inter-hunk-context 2 2>actual && + test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual + ' +done
This looks good as well
Quoted 1 line
test_done
As I said last time I do not think the tests below add any value. They also do not compensate for the removal of the tests for diff.context that are deleted above as they all pass -U on the commandline.
Quoted 31 lines
t/t4055-diff-context.sh +23
-0@@ -58,6 +58,36 @@ test_expect_success 'The -U option overrides diff.context' ' test_grep ! "^ firstline" output ' +test_expect_success 'The -U option overrides diff.context for "add"' ' + test_config diff.context 8 && + git add -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "commit"' ' + test_config diff.context 8 && + ! git commit -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "checkout"' ' + test_config diff.context 8 && + git checkout -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "stash"' ' + test_config diff.context 8 && + ! git stash -U4 -p >output && + test_grep ! "^ firstline" output +'
t/t4055-diff-context.sh test_expect_success 'The -U option overrides diff.context' ' · line 93
Quoted 10 lines
t/t4055-diff-context.sh +7
-0+ +test_expect_success 'The -U option overrides diff.context for "restore"' ' + test_config diff.context 8 && + git restore -U4 -p >output && + test_grep ! "^ firstline" output +' + test_expect_success 'diff.context honored by "diff"' ' test_config diff.context 8 && git diff >output &&
Thanks
Phillip
Quoted 9 lines · Junio C Hamano
Quoted 7 lines · Leon Michalak via GitGitGadget
Changes since v3:
* Update commit descriptions
* Read struct properties directly instead of assigning to variables first
* Simplify config setting / error checking
* Remove redundant tests in later commit as they were replaced with bettertest(s)
I've left some comments on patch 4 about this. It seems to me that it is deleting useful tests and replacing them with redundant tests.
Quoted 4 lines
Quoted 4 lines
* Change tests to use single quotes (this messes with the grep so was unable to explicitly test single quotes in the error messages, so decided to use regex . instead, which is what some other tests that have this problem seem to use as well)
Thanks for doing that
Quoted 4 lines
All of the above looked reasonably well done. Will replace.
Unless there are objections, let me mark the topic for 'next' soonish.
I think we want to sort out the test changes in patch 4. Previously we discussed centralizing the option parsing in that patch as well but we can always do that as a follow up later.
Thanks
Phillip
Quoted 7 lines · Phillip Wood
Quoted 3 lines
All of the above looked reasonably well done. Will replace. Unless there are objections, let me mark the topic for 'next' soonish.
I think we want to sort out the test changes in patch 4. Previously we discussed centralizing the option parsing in that patch as well but we can always do that as a follow up later.
Yeah, the tests can probably use a bit more polish before we can move forward. Thanks for carefully reading them over.
Re: [PATCH v4 4/4] add-patch: add diff.context command line overrides
In reply to Phillip WoodHey Philip, looking again for a second time and re-reading previous replies on this thread, I think I misunderstood a previous reply.
I will add these back as soon as I can get back to the PC, thanks for spotting that!
Quoted 151 lines · Phillip Wood
Hi Leon
Quoted 6 lines · Leon Michalak via GitGitGadget
From: Leon Michalak <[email protected]>
This patch compliments the previous commit, where builtins that use add-patch infrastructure now respect diff.context and diff.interHunkContext file configurations.
Quoted 7 lines
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.
Thanks for updating the quoting in the tests. Unfortunately this patch now deletes the tests added in the last commit which I don't think is correct.
t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1234
Quoted 3 lines
t/t3701-add-interactive.sh +0
-2-test_expect_success 'add -p respects diff.context' ' - test_write_lines a b c d e f g h i j k l m >file &&I think there is some confusion here - why are we deleting the tests added in the last commit? This removes the test coverage for diff.context and diff.interHunkContext
Quoted 21 lines
t/t3701-add-interactive.sh +17
-3+for cmd in add checkout restore 'commit -m file' +do + test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" ' + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && + git add file && + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && + echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ + $cmd -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual + ' +done + +test_expect_success 'reset accepts -U and --inter-hunk-context' ' + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && + git commit -m file file && + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && git add file && - test_write_lines a b c d e f G h i j k l m >file && - echo y | git -c diff.context=5 add -p >actual && - test_grep "@@ -2,11 +2,11 @@" actual + echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1246
Quoted 10 lines
t/t3701-add-interactive.sh +2
-6+ reset -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual ' -test_expect_success 'add -p respects diff.interHunkContext' ' - test_write_lines a b c d e f g h i j k l m n o p q r s >file && - git add file && - test_write_lines a b c d E f g i i j k l m N o p q r s >file && - echo y | git -c diff.interhunkcontext=2 add -p >actual && - test_grep "@@ -2,16 +2,16 @@" actualThis is also deleting a test added in the last patch
Quoted 4 lines
t/t3701-add-interactive.sh +4
-0+test_expect_success 'stash accepts -U and --inter-hunk-context' ' + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && + git commit -m file file && + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1253
Quoted 10 lines
t/t3701-add-interactive.sh +3
-5+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ + stash -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual ' -test_expect_success 'add -p rejects negative diff.context' ' - test_config diff.context -1 && - test_must_fail git add -p 2>output && - test_grep "diff.context cannot be negative" output -'and so is this. The tests you're adding look good but we shouldn't be deleting the existing ones.
Quoted 7 lines
t/t3701-add-interactive.sh +7
-0+for cmd in add checkout commit reset restore "stash save" "stash push" +do + test_expect_success "$cmd rejects invalid context options" ' + test_must_fail git $cmd -p -U -3 2>actual && + cat actual | echo && + test_grep -e ".--unified. cannot be negative" actual && +t/t3701-add-interactive.sh test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' · line 1280
Quoted 10 lines
t/t3701-add-interactive.sh +10
-0+ test_must_fail git $cmd -p --inter-hunk-context -3 2>actual && + test_grep -e ".--inter-hunk-context. cannot be negative" actual && + + test_must_fail git $cmd -U 7 2>actual && + test_grep -E ".--unified. requires .(--interactive/)?--patch." actual && + + test_must_fail git $cmd --inter-hunk-context 2 2>actual && + test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual + ' +doneThis looks good as well
Quoted 1 line
test_doneAs I said last time I do not think the tests below add any value. They also do not compensate for the removal of the tests for diff.context that are deleted above as they all pass -U on the commandline.
Quoted 31 lines
t/t4055-diff-context.sh +23
-0@@ -58,6 +58,36 @@ test_expect_success 'The -U option overrides diff.context' ' test_grep ! "^ firstline" output ' +test_expect_success 'The -U option overrides diff.context for "add"' ' + test_config diff.context 8 && + git add -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "commit"' ' + test_config diff.context 8 && + ! git commit -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "checkout"' ' + test_config diff.context 8 && + git checkout -U4 -p >output && + test_grep ! "^ firstline" output +' + +test_expect_success 'The -U option overrides diff.context for "stash"' ' + test_config diff.context 8 && + ! git stash -U4 -p >output && + test_grep ! "^ firstline" output +'t/t4055-diff-context.sh test_expect_success 'The -U option overrides diff.context' ' · line 93
Quoted 10 lines
t/t4055-diff-context.sh +7
-0+ +test_expect_success 'The -U option overrides diff.context for "restore"' ' + test_config diff.context 8 && + git restore -U4 -p >output && + test_grep ! "^ firstline" output +' + test_expect_success 'diff.context honored by "diff"' ' test_config diff.context 8 && git diff >output &&Thanks
Phillip
Re: [PATCH v4 4/4] add-patch: add diff.context command line overrides
Apologies for the top-posting above, this is not my regular workflow!
Re: [PATCH v4 4/4] add-patch: add diff.context command line overrides
In reply to Leon MichalakHi Leon
Here is a fixup commit for the tests which can be squashed into patch 4
Best Wishes
Phillip
---- 8< ----
From: Phillip Wood <[email protected]>
Subject: [PATCH] fixup! add-patch: add diff.context command line overrides
Restore the test coverage for diff.context and diff.interHunkContext added in f08d4ae6e56 (add-patch: respect diff.context configuration, 2025-07-19) and remove the redunant tests in t4055 added by bd6d6ba1321 (add-patch: add diff.context command line overrides, 2025-07-19) which duplicate the coverage of the tests added to t3071 in the same commit.
--- t/t3701-add-interactive.sh | 22 ++++++++++++++++++++++ t/t4055-diff-context.sh | 30 ------------------------------ 2 files changed, 22 insertions(+), 30 deletions(-)
t/t3701-add-interactive.sh +22 -0
@@ -1230,6 +1230,28 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'add -p respects diff.context' ' + test_write_lines a b c d e f g h i j k l m >file && + git add file && + test_write_lines a b c d e f G h i j k l m >file && + echo y | git -c diff.context=5 add -p >actual && + test_grep "@@ -2,11 +2,11 @@" actual +' + +test_expect_success 'add -p respects diff.interHunkContext' ' + test_write_lines a b c d e f g h i j k l m n o p q r s >file && + git add file && + test_write_lines a b c d E f g i i j k l m N o p q r s >file && + echo y | git -c diff.interhunkcontext=2 add -p >actual && + test_grep "@@ -2,16 +2,16 @@" actual +' + +test_expect_success 'add -p rejects negative diff.context' ' + test_config diff.context -1 && + test_must_fail git add -p 2>output && + test_grep "diff.context cannot be negative" output +' + for cmd in add checkout restore 'commit -m file' do test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" '
t/t4055-diff-context.sh +0 -30
@@ -58,36 +58,6 @@ test_expect_success 'The -U option overrides diff.context' ' test_grep ! "^ firstline" output ' -test_expect_success 'The -U option overrides diff.context for "add"' ' - test_config diff.context 8 && - git add -U4 -p >output && - test_grep ! "^ firstline" output -' - -test_expect_success 'The -U option overrides diff.context for "commit"' ' - test_config diff.context 8 && - ! git commit -U4 -p >output && - test_grep ! "^ firstline" output -' - -test_expect_success 'The -U option overrides diff.context for "checkout"' ' - test_config diff.context 8 && - git checkout -U4 -p >output && - test_grep ! "^ firstline" output -' - -test_expect_success 'The -U option overrides diff.context for "stash"' ' - test_config diff.context 8 && - ! git stash -U4 -p >output && - test_grep ! "^ firstline" output -' - -test_expect_success 'The -U option overrides diff.context for "restore"' ' - test_config diff.context 8 && - git restore -U4 -p >output && - test_grep ! "^ firstline" output -' - test_expect_success 'diff.context honored by "diff"' ' test_config diff.context 8 && git diff >output &&
Signature · 1 line
2.49.0.897.gfad3eb7d210
v5 cover Better support for customising context lines in --patch commands
In reply to Leon Michalak via GitGitGadgetThis series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"
The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Changes since v1:
* Update commit descriptions
* Update tests to use the more modern and robust test_grep and test_config utils
* Reword some documentation / user messages
* Ensure each commit is atomic and builds/passes tests on it's own
* Make new command line options DRY
* Add tests for interhunk context interaction
* Error if context config/command line options are negative
* Drop previous last commit to do with new subcommand for --interactive add/commit. My motivations behind this patch series originally where quite simple, just for add-patch commands to respect context configs. This subcommand, after the discussion in v1, will require more thought and a larger implementation that what I had anticipated. I would prefer to leave this for another time as it's the least impactful but the most time intensive and complicated idea.
Changes since v2:
* Update tests to only test single command (following Philip's suggestion)
* Add negative option checks
* Minor commit re-wording
Changes since v3:
* Update commit descriptions
* Read struct properties directly instead of assigning to variables first
* Simplify config setting / error checking
* Remove redundant tests in later commit as they were replaced with better test(s)
* Change tests to use single quotes (this messes with the grep so was unable to explicitly test single quotes in the error messages, so decided to use regex . instead, which is what some other tests that have this problem seem to use as well)
Changes since v4:
* Add back tests to maintain good coverage and remove redundant tests
Leon Michalak (4):
t: use test_grep in t3701 and t4055
t: use test_config in t4055
add-patch: respect diff.context configuration
add-patch: add diff.context command line overrides
Documentation/diff-context-options.adoc | 10 ++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 45 +++++++-- add-interactive.h | 17 +++- add-patch.c | 14 ++- builtin/add.c | 21 ++++- builtin/checkout.c | 31 +++++- builtin/commit.c | 16 +++- builtin/reset.c | 17 +++- builtin/stash.c | 56 ++++++++--- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 119 +++++++++++++++++++----- t/t4055-diff-context.sh | 42 ++++----- t/t9902-completion.sh | 2 + 20 files changed, 324 insertions(+), 83 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
base-commit: cf6f63ea6bf35173e02e18bdc6a4ba41288acff9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1915%2FNinjaInShade%2Finteractive-patch-context-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1915/NinjaInShade/interactive-patch-context-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/1915
Range-diff vs v4:
1: bbb2bc7082b = 1: bbb2bc7082b t: use test_grep in t3701 and t4055
2: feace2d3676 = 2: feace2d3676 t: use test_config in t4055
3: 994029d6602 = 3: 994029d6602 add-patch: respect diff.context configuration
4: 2774b930406 ! 4: 9731e5b76fb add-patch: add diff.context command line overrides
@@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *
OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
## t/t3701-add-interactive.sh ##
-@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' '
- test_cmp expect actual
+@@ t/t3701-add-interactive.sh: test_expect_success 'add -p rejects negative diff.context' '
+ test_grep "diff.context cannot be negative" output
'
--test_expect_success 'add -p respects diff.context' '
-- test_write_lines a b c d e f g h i j k l m >file &&
+for cmd in add checkout restore 'commit -m file'
+do
+ test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" '
@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.
+ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
+ git commit -m file file &&
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
- git add file &&
-- test_write_lines a b c d e f G h i j k l m >file &&
-- echo y | git -c diff.context=5 add -p >actual &&
-- test_grep "@@ -2,11 +2,11 @@" actual
++ git add file &&
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ reset -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
- '
-
--test_expect_success 'add -p respects diff.interHunkContext' '
-- test_write_lines a b c d e f g h i j k l m n o p q r s >file &&
-- git add file &&
-- test_write_lines a b c d E f g i i j k l m N o p q r s >file &&
-- echo y | git -c diff.interhunkcontext=2 add -p >actual &&
-- test_grep "@@ -2,16 +2,16 @@" actual
++'
++
+test_expect_success 'stash accepts -U and --inter-hunk-context' '
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
+ git commit -m file file &&
@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ stash -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
- '
-
--test_expect_success 'add -p rejects negative diff.context' '
-- test_config diff.context -1 &&
-- test_must_fail git add -p 2>output &&
-- test_grep "diff.context cannot be negative" output
--'
++'
++
+for cmd in add checkout commit reset restore "stash save" "stash push"
+do
+ test_expect_success "$cmd rejects invalid context options" '
@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.
+ test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual
+ '
+done
-
- test_done
-
- ## t/t4055-diff-context.sh ##
-@@ t/t4055-diff-context.sh: test_expect_success 'The -U option overrides diff.context' '
- test_grep ! "^ firstline" output
- '
-
-+test_expect_success 'The -U option overrides diff.context for "add"' '
-+ test_config diff.context 8 &&
-+ git add -U4 -p >output &&
-+ test_grep ! "^ firstline" output
-+'
-+
-+test_expect_success 'The -U option overrides diff.context for "commit"' '
-+ test_config diff.context 8 &&
-+ ! git commit -U4 -p >output &&
-+ test_grep ! "^ firstline" output
-+'
-+
-+test_expect_success 'The -U option overrides diff.context for "checkout"' '
-+ test_config diff.context 8 &&
-+ git checkout -U4 -p >output &&
-+ test_grep ! "^ firstline" output
-+'
+
-+test_expect_success 'The -U option overrides diff.context for "stash"' '
-+ test_config diff.context 8 &&
-+ ! git stash -U4 -p >output &&
-+ test_grep ! "^ firstline" output
-+'
-+
-+test_expect_success 'The -U option overrides diff.context for "restore"' '
-+ test_config diff.context 8 &&
-+ git restore -U4 -p >output &&
-+ test_grep ! "^ firstline" output
-+'
-+
- test_expect_success 'diff.context honored by "diff"' '
- test_config diff.context 8 &&
- git diff >output &&
+ test_done
## t/t9902-completion.sh ##
@@ t/t9902-completion.sh: test_expect_success 'double dash "git checkout"' 'Signature · 1 line
gitgitgadget
PATCH v5 2/4 t: use test_config in t4055
From: Leon Michalak <[email protected]>
Use the modern "test_config" test utility instead of manual"git config" as the former provides clean up on test completion.
This is a prerequisite to the commits that follow which add to this test file.
--- t/t4055-diff-context.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
t/t4055-diff-context.sh +7 -7
@@ -47,43 +47,43 @@ test_expect_success 'the default number of context lines is 3' ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && test_grep ! firstline output && - git config diff.context 8 && + test_config diff.context 8 && git log -1 -p >output && test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' - git config diff.context 8 && + test_config diff.context 8 && git log -U4 -1 >output && test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' - git config diff.context 8 && + test_config diff.context 8 && git diff >output && test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' - git config diff.context 8 && + test_config diff.context 8 && git diff-files -p >output && test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' ' - git config diff.context no && + test_config diff.context no && test_must_fail git diff 2>output && test_grep "bad numeric config value" output ' test_expect_success 'negative integer config parsing' ' - git config diff.context -1 && + test_config diff.context -1 && test_must_fail git diff 2>output && test_grep "bad config variable" output ' test_expect_success '-U0 is valid, so is diff.context=0' ' - git config diff.context 0 && + test_config diff.context 0 && git diff >output && test_grep "^-ADDED" output && test_grep "^+MODIFIED" output
Signature · 1 line
gitgitgadget
PATCH v5 1/4 t: use test_grep in t3701 and t4055
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
As a preparatory clean-up, use the "test_grep" test utility instead of regular "grep" which provides better debug information if tests fail.
--- t/t3701-add-interactive.sh | 48 +++++++++++++++++++------------------- t/t4055-diff-context.sh | 28 +++++++++++----------- 2 files changed, 38 insertions(+), 38 deletions(-)
t/t3701-add-interactive.sh +24 -24
@@ -63,7 +63,7 @@ test_expect_success 'setup (initial)' ' ' test_expect_success 'status works (initial)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'setup expected' '
@@ -86,7 +86,7 @@ test_expect_success 'revert works (initial)' ' git add file && test_write_lines r 1 | git add -i && git ls-files >output && - ! grep . output + test_grep ! . output ' test_expect_success 'add untracked (multiple)' '
@@ -109,7 +109,7 @@ test_expect_success 'setup (commit)' ' ' test_expect_success 'status works (commit)' ' git add -i </dev/null >output && - grep "+1/-0 *+2/-0 file" output + test_grep "+1/-0 *+2/-0 file" output ' test_expect_success 'update can stage deletions' '
@@ -141,7 +141,7 @@ test_expect_success 'revert works (commit)' ' git add file && test_write_lines r 1 | git add -i && git add -i </dev/null >output && - grep "unchanged *+3/-0 file" output + test_grep "unchanged *+3/-0 file" output ' test_expect_success 'reject multi-key input' '
@@ -185,7 +185,7 @@ test_expect_success 'setup fake editor' ' test_expect_success 'bad edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -198,7 +198,7 @@ test_expect_success 'setup patch' ' test_expect_success 'garbage edit rejected' ' git reset && test_write_lines e n d | git add -p >output && - grep "hunk does not apply" output + test_grep "hunk does not apply" output ' test_expect_success 'setup patch' '
@@ -313,8 +313,8 @@ test_expect_success FILEMODE 'stage mode and hunk' ' chmod +x file && printf "y\\ny\\n" | git add -p && git diff --cached file >out && - grep "new mode" out && - grep "+content" out && + test_grep "new mode" out && + test_grep "+content" out && git diff file >out && test_must_be_empty out '
@@ -636,7 +636,7 @@ test_expect_success 'split hunk "add -p (edit)"' ' printf "%s\n" s e q n q q | EDITOR=: git add -p && git diff >actual && - ! grep "^+15" actual + test_grep ! "^+15" actual ' test_expect_success 'split hunk "add -p (no, yes, edit)"' '
@@ -648,7 +648,7 @@ test_expect_success 'split hunk "add -p (no, yes, edit)"' ' EDITOR=: git add -p 2>error && test_must_be_empty error && git diff >actual && - ! grep "^+31" actual + test_grep ! "^+31" actual ' test_expect_success 'split hunk with incomplete line at end' '
@@ -682,7 +682,7 @@ test_expect_success 'edit, adding lines to the first hunk' ' EDITOR=./fake_editor.sh git add -p 2>error && test_must_be_empty error && git diff --cached >actual && - grep "^+22" actual + test_grep "^+22" actual ' test_expect_success 'patch mode ignores unmerged entries' '
@@ -696,7 +696,7 @@ test_expect_success 'patch mode ignores unmerged entries' ' test_must_fail git merge side && echo changed >non-conflict.t && echo y | git add -p >output && - ! grep a/conflict.t output && + test_grep ! a/conflict.t output && cat >expected <<-\EOF && * Unmerged path conflict.t diff --git a/non-conflict.t b/non-conflict.t
@@ -728,7 +728,7 @@ test_expect_success 'diffs can be colorized' ' # We do not want to depend on the exact coloring scheme # git uses for diffs, so just check that we saw some kind of color. - grep "$(printf "\\033")" output + test_grep "$(printf "\\033")" output ' test_expect_success 'colors can be overridden' '
@@ -743,7 +743,7 @@ test_expect_success 'colors can be overridden' ' -c color.interactive.error=blue \ add -i 2>err.raw <input && test_decode_color <err.raw >err && - grep "<BLUE>Huh (trigger)?<RESET>" err && + test_grep "<BLUE>Huh (trigger)?<RESET>" err && test_write_lines help quit >input && force_color git \
@@ -863,7 +863,7 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' printf y >y && force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y && test_decode_color <output.raw >output && - grep "old<" output + test_grep "old<" output ' test_expect_success 'diffFilter filters diff' '
@@ -876,7 +876,7 @@ test_expect_success 'diffFilter filters diff' ' # avoid depending on the exact coloring or content of the prompts, # and just make sure we saw our diff prefixed - grep foo:.*content output + test_grep foo:.*content output ' test_expect_success 'detect bogus diffFilter output' '
@@ -886,7 +886,7 @@ test_expect_success 'detect bogus diffFilter output' ' test_config interactive.diffFilter "sed 6d" && printf y >y && force_color test_must_fail git add -p <y >output 2>&1 && - grep "mismatched output" output + test_grep "mismatched output" output ' test_expect_success 'handle iffy colored hunk headers' '
@@ -896,7 +896,7 @@ test_expect_success 'handle iffy colored hunk headers' ' printf n >n && force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \ add -p >output 2>&1 <n && - grep "^XX$" output + test_grep "^XX$" output ' test_expect_success 'handle very large filtered diff' '
@@ -1002,7 +1002,7 @@ test_expect_success 'add -p does not expand argument lists' ' # update it, but we want to be sure that our "." pathspec # was not expanded into the argument list of any command. # So look only for "not-changed". - ! grep -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out + test_grep ! -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out ' test_expect_success 'hunk-editing handles custom comment char' '
@@ -1072,21 +1072,21 @@ test_expect_success 'setup different kinds of dirty submodules' ' test_expect_success 'status ignores dirty submodules (except HEAD)' ' git -C for-submodules add -i </dev/null >output && - grep dirty-head output && - grep dirty-both-ways output && - ! grep dirty-otherwise output + test_grep dirty-head output && + test_grep dirty-both-ways output && + test_grep ! dirty-otherwise output ' test_expect_success 'handle submodules' ' echo 123 >>for-submodules/dirty-otherwise/initial.t && force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 && - grep "No changes" output && + test_grep "No changes" output && force_color git -C for-submodules add -p dirty-head >output 2>&1 <y && git -C for-submodules ls-files --stage dirty-head >actual && rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" && - grep "$rev" actual + test_grep "$rev" actual ' test_expect_success 'set up pathological context' '
t/t4055-diff-context.sh +14 -14
@@ -38,36 +38,36 @@ test_expect_success 'setup' ' test_expect_success 'the default number of context lines is 3' ' git diff >output && - ! grep "^ d" output && - grep "^ e" output && - grep "^ j" output && - ! grep "^ k" output + test_grep ! "^ d" output && + test_grep "^ e" output && + test_grep "^ j" output && + test_grep ! "^ k" output ' test_expect_success 'diff.context honored by "log"' ' git log -1 -p >output && - ! grep firstline output && + test_grep ! firstline output && git config diff.context 8 && git log -1 -p >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'The -U option overrides diff.context' ' git config diff.context 8 && git log -U4 -1 >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'diff.context honored by "diff"' ' git config diff.context 8 && git diff >output && - grep "^ firstline" output + test_grep "^ firstline" output ' test_expect_success 'plumbing not affected' ' git config diff.context 8 && git diff-files -p >output && - ! grep "^ firstline" output + test_grep ! "^ firstline" output ' test_expect_success 'non-integer config parsing' '
@@ -85,8 +85,8 @@ test_expect_success 'negative integer config parsing' ' test_expect_success '-U0 is valid, so is diff.context=0' ' git config diff.context 0 && git diff >output && - grep "^-ADDED" output && - grep "^+MODIFIED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output ' test_expect_success '-U2147483647 works' '
@@ -94,9 +94,9 @@ test_expect_success '-U2147483647 works' ' test_line_count = 16 x && git diff -U2147483647 >output && test_line_count = 22 output && - grep "^-ADDED" output && - grep "^+MODIFIED" output && - grep "^+APPENDED" output + test_grep "^-ADDED" output && + test_grep "^+MODIFIED" output && + test_grep "^+APPENDED" output ' test_done
Signature · 1 line
gitgitgadget
PATCH v5 3/4 add-patch: respect diff.context configuration
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
Various builtins that use add-patch infrastructure do not respect the user's diff.context and diff.interHunkContext file configurations.
The user may be used to seeing their diffs with customized context size, but not in the patches "git add -p" shows them to pick from.
Teach add-patch infrastructure to read these configuration variables and pass their values when spawning the underlying plumbing commands as their command line option.
--- add-interactive.c | 9 +++++++++ add-interactive.h | 1 + add-patch.c | 9 ++++++--- t/t3701-add-interactive.sh | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-)
add-interactive.c +9 -0
@@ -41,6 +41,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)const char *value; s->r = r; + s->context =-1 ; + s->interhunkcontext =-1 ;if (repo_config_get_value (r,"color.interactive" , &value)) s->use_color =-1 ;
@@ -78,6 +80,13 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_string (r,"diff.algorithm" , &s->interactive_diff_algorithm); +if (!repo_config_get_int (r,"diff.context" , &s->context)) +if (s->context <0 ) +die (_ ("%s cannot be negative" ),"diff.context" ); +if (!repo_config_get_int (r,"diff.interHunkContext" , &s->interhunkcontext)) +if (s->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"diff.interHunkContext" ); +repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL );
add-interactive.h +1 -0
@@ -18,6 +18,7 @@ struct add_i_state {int use_single_key;char *interactive_diff_filter, *interactive_diff_algorithm; +int context, interhunkcontext; };void init_add_i_state (struct add_i_state *s,struct repository *r);
add-patch.c +6 -3
@@ -414,7 +414,6 @@ static int normalize_marker(const char *p)static int parse_diff (struct add_p_state *s,const struct pathspec *ps) {struct strvec args =STRVEC_INIT ; -const char *diff_algorithm = s->s.interactive_diff_algorithm;struct strbuf *plain = &s->plain, *colored =NULL ;struct child_process cp =CHILD_PROCESS_INIT ;char *p, *pend, *colored_p =NULL , *colored_pend =NULL , marker ='\0' ;
@@ -424,8 +423,12 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)int res;strvec_pushv (&args, s->mode->diff_cmd); -if (diff_algorithm) -strvec_pushf (&args,"--diff-algorithm=%s" , diff_algorithm); +if (s->s.context !=-1 ) +strvec_pushf (&args,"--unified=%i" , s->s.context); +if (s->s.interhunkcontext !=-1 ) +strvec_pushf (&args,"--inter-hunk-context=%i" , s->s.interhunkcontext); +if (s->s.interactive_diff_algorithm) +strvec_pushf (&args,"--diff-algorithm=%s" , s->s.interactive_diff_algorithm);if (s->revision) {struct object_id oid; strvec_push(&args,
t/t3701-add-interactive.sh +22 -0
@@ -1230,4 +1230,26 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'add -p respects diff.context' ' + test_write_lines a b c d e f g h i j k l m >file && + git add file && + test_write_lines a b c d e f G h i j k l m >file && + echo y | git -c diff.context=5 add -p >actual && + test_grep "@@ -2,11 +2,11 @@" actual +' + +test_expect_success 'add -p respects diff.interHunkContext' ' + test_write_lines a b c d e f g h i j k l m n o p q r s >file && + git add file && + test_write_lines a b c d E f g i i j k l m N o p q r s >file && + echo y | git -c diff.interhunkcontext=2 add -p >actual && + test_grep "@@ -2,16 +2,16 @@" actual +' + +test_expect_success 'add -p rejects negative diff.context' ' + test_config diff.context -1 && + test_must_fail git add -p 2>output && + test_grep "diff.context cannot be negative" output +' + test_done
Signature · 1 line
gitgitgadget
PATCH v5 4/4 add-patch: add diff.context command line overrides
In reply to Leon Michalak via GitGitGadgetFrom: Leon Michalak <[email protected]>
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.
--- Documentation/diff-context-options.adoc | 10 +++++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 36 ++++++++++++---- add-interactive.h | 16 +++++-- add-patch.c | 5 ++- builtin/add.c | 21 ++++++++-- builtin/checkout.c | 31 ++++++++++++-- builtin/commit.c | 16 ++++++- builtin/reset.c | 17 +++++++- builtin/stash.c | 56 ++++++++++++++++++++----- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 49 ++++++++++++++++++++++ t/t9902-completion.sh | 2 + 19 files changed, 241 insertions(+), 35 deletions(-) create mode 100644 Documentation/diff-context-options.adoc
Documentation/diff-context-options.adoc new file +10 -0
@@ -0,0 +1,10 @@ +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context. Defaults to `diff.context` + or 3 if the config option is unset. + +`--inter-hunk-context=<n>`:: + Show the context between diff hunks, up to the specified _<number>_ + of lines, thereby fusing hunks that are close to each other. + Defaults to `diff.interHunkContext` or 0 if the config option + is unset.
Documentation/git-add.adoc +2 -0
@@ -104,6 +104,8 @@ This effectively runs `add --interactive`, but bypasses the initial command menu and directly jumps to the `patch` subcommand. See ``Interactive mode'' for details. +include::diff-context-options.adoc[] + `-e`:: `--edit`:: Open the diff vs. the index in an editor and let the user
Documentation/git-checkout.adoc +2 -0
@@ -289,6 +289,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. +include::diff-context-options.adoc[] + `--ignore-other-worktrees`:: `git checkout` refuses when the wanted branch is already checked out or otherwise in use by another worktree. This option makes
Documentation/git-commit.adoc +2 -0
@@ -76,6 +76,8 @@ OPTIONS which changes to commit. See linkgit:git-add[1] for details. +include::diff-context-options.adoc[] + `-C <commit>`:: `--reuse-message=<commit>`:: Take an existing _<commit>_ object, and reuse the log message
Documentation/git-reset.adoc +2 -0
@@ -125,6 +125,8 @@ OPTIONS separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). +include::diff-context-options.adoc[] + `--`:: Do not interpret any more arguments as options.
Documentation/git-restore.adoc +2 -0
@@ -52,6 +52,8 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. +include::diff-context-options.adoc[] + `-W`:: `--worktree`:: `-S`::
Documentation/git-stash.adoc +2 -0
@@ -208,6 +208,8 @@ to learn how to operate the `--patch` mode. The `--patch` option implies `--keep-index`. You can use `--no-keep-index` to override this. +include::diff-context-options.adoc[] + -S:: --staged:: This option is only valid for `push` and `save` commands.
add-interactive.c +28 -8
@@ -36,7 +36,8 @@ static void init_color(struct repository *r, struct add_i_state *s,free (key); } -void init_add_i_state (struct add_i_state *s,struct repository *r) +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt) {const char *value;
@@ -90,6 +91,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)repo_config_get_bool (r,"interactive.singlekey" , &s->use_single_key);if (s->use_single_key)setbuf (stdin,NULL ); + +if (add_p_opt->context !=-1 ) { +if (add_p_opt->context <0 ) +die (_ ("%s cannot be negative" ),"--unified" ); + s->context = add_p_opt->context; + } +if (add_p_opt->interhunkcontext !=-1 ) { +if (add_p_opt->interhunkcontext <0 ) +die (_ ("%s cannot be negative" ),"--inter-hunk-context" ); + s->interhunkcontext = add_p_opt->interhunkcontext; + } }void clear_add_i_state (struct add_i_state *s)
@@ -978,6 +990,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps, opts->prompt =N_ ("Patch update" ); count =list_and_choose (s, files, opts);if (count >0 ) { +struct add_p_opt add_p_opt = { + .context = s->context, + .interhunkcontext = s->interhunkcontext, + };struct strvec args =STRVEC_INIT ;struct pathspec ps_selected = {0 };
@@ -988,7 +1004,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,parse_pathspec (&ps_selected,PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL ,PATHSPEC_LITERAL_PATH ,"" , args.v); - res =run_add_p (s->r,ADD_P_ADD ,NULL , &ps_selected); + res =run_add_p (s->r,ADD_P_ADD , &add_p_opt,NULL , &ps_selected);strvec_clear (&args);clear_pathspec (&ps_selected); }
@@ -1023,10 +1039,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,if (count >0 ) {struct child_process cmd =CHILD_PROCESS_INIT ; -strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" , -oid_to_hex (!is_initial ? &oid : - s->r->hash_algo->empty_tree), -"--" ,NULL ); +strvec_pushl (&cmd.args,"git" ,"diff" ,"-p" ,"--cached" ,NULL ); +if (s->context !=-1 ) +strvec_pushf (&cmd.args,"--unified=%i" , s->context); +if (s->interhunkcontext !=-1 ) +strvec_pushf (&cmd.args,"--inter-hunk-context=%i" , s->interhunkcontext); +strvec_pushl (&cmd.args,oid_to_hex (!is_initial ? &oid : + s->r->hash_algo->empty_tree),"--" ,NULL );for (i =0 ; i < files->items.nr; i++)if (files->selected[i]) strvec_push(&cmd.args,
@@ -1119,7 +1138,8 @@ static void command_prompt_help(struct add_i_state *s) _("(empty) select nothing")); } -int run_add_i (struct repository *r,const struct pathspec *ps) +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt) {struct add_i_state s = {NULL };struct print_command_item_data data = {"[" ,"]" };
@@ -1162,7 +1182,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps) ->util = util; } -init_add_i_state (&s, r); +init_add_i_state (&s, r, add_p_opt);/* * When color was asked for, use the prompt color for
add-interactive.h +13 -3
@@ -3,6 +3,13 @@#include "color.h" +struct add_p_opt { +int context; +int interhunkcontext; +}; + +#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 } +struct add_i_state {struct repository *r;int use_color;
@@ -21,12 +28,14 @@ struct add_i_state {int context, interhunkcontext; }; -void init_add_i_state (struct add_i_state *s,struct repository *r); +void init_add_i_state (struct add_i_state *s,struct repository *r, +struct add_p_opt *add_p_opt);void clear_add_i_state (struct add_i_state *s);struct repository ;struct pathspec ; -int run_add_i (struct repository *r,const struct pathspec *ps); +int run_add_i (struct repository *r,const struct pathspec *ps, +struct add_p_opt *add_p_opt);enum add_p_mode {ADD_P_ADD ,
@@ -37,6 +46,7 @@ enum add_p_mode { };int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps); +struct add_p_opt *o,const char *revision, +const struct pathspec *ps);#endif
add-patch.c +3 -2
@@ -1763,14 +1763,15 @@ soft_increment: }int run_add_p (struct repository *r,enum add_p_mode mode, -const char *revision,const struct pathspec *ps) +struct add_p_opt *o,const char *revision, +const struct pathspec *ps) {struct add_p_state s = { { r },STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT ,STRBUF_INIT };size_t i, binary_count =0 ; -init_add_i_state (&s.s, r); +init_add_i_state (&s.s, r, o);if (mode ==ADD_P_STASH ) s.mode = &patch_mode_stash;
builtin/add.c +17 -4
@@ -29,6 +29,7 @@ static const char * const builtin_add_usage[] = { NULL };static int patch_interactive, add_interactive, edit_interactive; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int take_worktree_changes;static int add_renormalize;static int pathspec_file_nul;
@@ -157,7 +158,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch) +int patch,struct add_p_opt *add_p_opt) {struct pathspec pathspec;int ret;
@@ -169,9 +170,9 @@ int interactive_add(struct repository *repo, prefix, argv);if (patch) - ret = !!run_add_p (repo,ADD_P_ADD ,NULL , &pathspec); + ret = !!run_add_p (repo,ADD_P_ADD , add_p_opt,NULL , &pathspec);else - ret = !!run_add_i (repo, &pathspec); + ret = !!run_add_i (repo, &pathspec, add_p_opt);clear_pathspec (&pathspec);return ret;
@@ -253,6 +254,8 @@ static struct option builtin_add_options[] = {OPT_GROUP ("" ),OPT_BOOL ('i' ,"interactive" , &add_interactive,N_ ("interactive picking" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('e' ,"edit" , &edit_interactive,N_ ("edit current diff and apply" )),OPT__FORCE (&ignored_too,N_ ("allow adding otherwise ignored files" ),0 ), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -394,6 +397,11 @@ int cmd_add(int argc,prepare_repo_settings (repo); repo->settings.command_requires_full_index =0 ; +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +if (patch_interactive) add_interactive =1 ;if (add_interactive) {
@@ -401,7 +409,12 @@ int cmd_add(int argc,die (_ ("options '%s' and '%s' cannot be used together" ),"--dry-run" ,"--interactive/--patch" );if (pathspec_from_file)die (_ ("options '%s' and '%s' cannot be used together" ),"--pathspec-from-file" ,"--interactive/--patch" ); -exit (interactive_add (repo, argv +1 , prefix, patch_interactive)); +exit (interactive_add (repo, argv +1 , prefix, patch_interactive, &add_p_opt)); + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }if (edit_interactive) {
builtin/checkout.c +28 -3
@@ -61,6 +61,8 @@ static const char * const restore_usage[] = {struct checkout_opts {int patch_mode; +int patch_context; +int patch_interhunk_context;int quiet;int merge;int force;
@@ -104,7 +106,12 @@ struct checkout_opts {struct tree *source_tree; }; -#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 } +#define CHECKOUT_OPTS_INIT { \ + .conflict_style = -1, \ + .merge = -1, \ + .patch_context = -1, \ + .patch_interhunk_context = -1, \ +}struct branch_info {char *name;/* The short name used */
@@ -539,6 +546,10 @@ static int checkout_paths(const struct checkout_opts *opts,if (opts->patch_mode) {enum add_p_mode patch_mode; +struct add_p_opt add_p_opt = { + .context = opts->patch_context, + .interhunkcontext = opts->patch_interhunk_context, + };const char *rev = new_branch_info->name;char rev_oid[GIT_MAX_HEXSZ +1 ];
@@ -564,8 +575,8 @@ static int checkout_paths(const struct checkout_opts *opts,else BUG ("either flag must have been set, worktree=%d, index=%d" , opts->checkout_worktree, opts->checkout_index); -return !!run_add_p (the_repository, patch_mode, rev, - &opts->pathspec); +return !!run_add_p (the_repository, patch_mode, &add_p_opt, + rev, &opts->pathspec); }repo_hold_locked_index (the_repository, &lock_file,LOCK_DIE_ON_ERROR );
@@ -1738,6 +1749,8 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts, N_("checkout their version for unmerged files"), 3, PARSE_OPT_NONEG),OPT_BOOL ('p' ,"patch" , &opts->patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&opts->patch_context), +OPT_DIFF_INTERHUNK_CONTEXT (&opts->patch_interhunk_context),OPT_BOOL (0 ,"ignore-skip-worktree-bits" , &opts->ignore_skipworktree,N_ ("do not limit pathspecs to sparse entries only" )), OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
@@ -1780,6 +1793,18 @@ static int checkout_main(int argc, const char **argv, const char *prefix, argc =parse_options (argc, argv, prefix, options, usagestr, parseopt_flags); +if (opts->patch_context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (opts->patch_interhunk_context <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); + +if (!opts->patch_mode) { +if (opts->patch_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (opts->patch_interhunk_context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); + } +if (opts->show_progress <0 ) {if (opts->quiet) opts->show_progress =0 ;
builtin/commit.c +15 -1
@@ -19,6 +19,7 @@#include "environment.h" #include "diff.h" #include "commit.h" +#include "add-interactive.h" #include "gettext.h" #include "revision.h" #include "wt-status.h"
@@ -122,6 +123,7 @@ static const char *edit_message, *use_message;static char *fixup_message, *fixup_commit, *squash_message;static const char *fixup_prefix;static int all, also, interactive, patch_interactive, only, amend, signoff; +static struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;static int edit_flag =-1 ;/* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */
@@ -354,6 +356,11 @@ static const char *prepare_index(const char **argv, const char *prefix,const char *ret;char *path =NULL ; +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +if (is_status) refresh_flags |=REFRESH_UNMERGED ; parse_pathspec(&pathspec, 0,
@@ -400,7 +407,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env =xstrdup_or_null (getenv (INDEX_ENVIRONMENT ));setenv (INDEX_ENVIRONMENT , the_repository->index_file,1 ); -if (interactive_add (the_repository, argv, prefix, patch_interactive) !=0 ) +if (interactive_add (the_repository, argv, prefix, patch_interactive, &add_p_opt) !=0 )die (_ ("interactive add failed" )); the_repository->index_file = old_repo_index_file;
@@ -424,6 +431,11 @@ static const char *prepare_index(const char **argv, const char *prefix, commit_style =COMMIT_NORMAL ; ret =get_lock_file_path (&index_lock); goto out; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--interactive/--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--interactive/--patch" ); }/*
@@ -1722,6 +1734,8 @@ int cmd_commit(int argc,OPT_BOOL ('i' ,"include" , &also,N_ ("add specified files to index for commit" )),OPT_BOOL (0 ,"interactive" , &interactive,N_ ("interactively add files" )),OPT_BOOL ('p' ,"patch" , &patch_interactive,N_ ("interactively add changes" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('o' ,"only" , &only,N_ ("commit only specified files" )),OPT_BOOL ('n' ,"no-verify" , &no_verify,N_ ("bypass pre-commit and commit-msg hooks" )), OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
builtin/reset.c +15 -2
@@ -346,6 +346,7 @@ int cmd_reset(int argc,struct object_id oid;struct pathspec pathspec;int intent_to_add =0 ; +struct add_p_opt add_p_opt =ADD_P_OPT_INIT ;const struct option options[] = {OPT__QUIET (&quiet,N_ ("be quiet, only report errors" )), OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -370,6 +371,8 @@ int cmd_reset(int argc, PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),OPT_BOOL ('p' ,"patch" , &patch_mode,N_ ("select hunks interactively" )), +OPT_DIFF_UNIFIED (&add_p_opt.context), +OPT_DIFF_INTERHUNK_CONTEXT (&add_p_opt.interhunkcontext),OPT_BOOL ('N' ,"intent-to-add" , &intent_to_add,N_ ("record only the fact that removed paths will be added later" )), OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -420,6 +423,11 @@ int cmd_reset(int argc,oidcpy (&oid, &tree->object.oid); } +if (add_p_opt.context <-1 ) +die (_ ("'%s' cannot be negative" ),"--unified" ); +if (add_p_opt.interhunkcontext <-1 ) +die (_ ("'%s' cannot be negative" ),"--inter-hunk-context" ); +prepare_repo_settings (the_repository); the_repository->settings.command_requires_full_index =0 ;
@@ -427,9 +435,14 @@ int cmd_reset(int argc,if (reset_type !=NONE )die (_ ("options '%s' and '%s' cannot be used together" ),"--patch" ,"--{hard,mixed,soft}" );trace2_cmd_mode ("patch-interactive" ); - update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , rev, - &pathspec); + update_ref_status = !!run_add_p (the_repository,ADD_P_RESET , + &add_p_opt, rev, &pathspec); goto cleanup; + }else { +if (add_p_opt.context !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--unified" ,"--patch" ); +if (add_p_opt.interhunkcontext !=-1 ) +die (_ ("the option '%s' requires '%s'" ),"--inter-hunk-context" ,"--patch" ); }/* git reset tree [--] paths... can be used to
builtin/stash.c +45 -11
136 lines not on this page · raw message
commit.h +2 -1
@@ -2,6 +2,7 @@#define COMMIT_H #include "object.h" +#include "add-interactive.h" struct signature_check ;struct strbuf ;
@@ -257,7 +258,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);int interactive_add (struct repository *repo,const char **argv,const char *prefix, -int patch); +int patch,struct add_p_opt *add_p_opt);struct commit_extra_header {struct commit_extra_header *next;
parse-options.h +2 -0
@@ -616,6 +616,8 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);#define OPT_PATHSPEC_FROM_FILE (v) OPT_FILENAME(0, "pathspec-from-file", v, N_("read pathspec from file"))#define OPT_PATHSPEC_FILE_NUL (v) OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))#define OPT_AUTOSTASH (v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after")) +#define OPT_DIFF_UNIFIED (v) OPT_INTEGER_F('U', "unified", v, N_("generate diffs with <n> lines context"), PARSE_OPT_NONEG) +#define OPT_DIFF_INTERHUNK_CONTEXT (v) OPT_INTEGER_F(0, "inter-hunk-context", v, N_("show context between diff hunks up to the specified number of lines"), PARSE_OPT_NONEG)#define OPT_IPVERSION (v) \ OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \
t/t3701-add-interactive.sh +49 -0
53 lines not on this page · raw message
t/t9902-completion.sh +2 -0
@@ -2596,6 +2596,8 @@ test_expect_success 'double dash "git checkout"' ' --merge Z --conflict=Z --patch Z + --unified=Z + --inter-hunk-context=Z --ignore-skip-worktree-bits Z --ignore-other-worktrees Z --recurse-submodules Z
Signature · 1 line
gitgitgadget
Hi Leon
The range-diff below looks good to me. Thanks for working on this
Phillip
Quoted 216 lines · Leon Michalak via GitGitGadget
This series of patches attempt to give --interactive/--patch compatible builtins ("add", "commit", "checkout", "reset", "restore" and "stash") better support and nicer experience for configuring how many context lines are shown in diffs through a variety of ways.
Prior to these patches, the user could not choose how many context lines they saw in --patch commands (apart from one workaround by using GIT_DIFF_OPTS=-u<number> ..., however this isn't a good user experience or a persistent solution). Additionally, the behaviour around reading from the diff.context and diff.interHunkContext configs was also inconsistent with other diff generating commands such as "log -p".
The summarised changes below hopefully make this experience better and fix some inconsistencies:
* diff.context and diff.interHunkContext configs are now respected by --patch compatible commands
* --unified and --inter-hunk-context command line options have been added to --patch compatible commands (which take prescendence over file configs)
* "add" and "commit" in --interactive mode now expose a new "context" subcommand which configures the amount of context lines you wish to see in subsequent diffs generated from other subcommands such as "patch" or "diff"The original discussion for this can be read at:
* https://lore.kernel.org/git/CAP9jKjGb-Rcr=RLJEzeFdtrekYM+qmHy+1T1fykU3n9cV4GhGw@mail.gmail.com/
Changes since v1:
* Update commit descriptions
* Update tests to use the more modern and robusttest_grepandtest_configutils
* Reword some documentation / user messages
* Ensure each commit is atomic and builds/passes tests on it's own
* Make new command line options DRY
* Add tests for interhunk context interaction
* Error if context config/command line options are negative
* Drop previous last commit to do with new subcommand for --interactive add/commit. My motivations behind this patch series originally where quite simple, just for add-patch commands to respect context configs. This subcommand, after the discussion in v1, will require more thought and a larger implementation that what I had anticipated. I would prefer to leave this for another time as it's the least impactful but the most time intensive and complicated idea.Changes since v2:
* Update tests to only test single command (following Philip's suggestion)
* Add negative option checks
* Minor commit re-wordingChanges since v3:
* Update commit descriptions
* Read struct properties directly instead of assigning to variables first
* Simplify config setting / error checking
* Remove redundant tests in later commit as they were replaced with bettertest(s)* Change tests to use single quotes (this messes with the grep so was unable to explicitly test single quotes in the error messages, so decided to use regex . instead, which is what some other tests that have this problem seem to use as well)
Changes since v4:
* Add back tests to maintain good coverage and remove redundant tests
Leon Michalak (4):
t: usetest_grepin t3701 and t4055
t: usetest_configin t4055
add-patch: respect diff.context configuration
add-patch: add diff.context command line overridesDocumentation/diff-context-options.adoc | 10 ++ Documentation/git-add.adoc | 2 + Documentation/git-checkout.adoc | 2 + Documentation/git-commit.adoc | 2 + Documentation/git-reset.adoc | 2 + Documentation/git-restore.adoc | 2 + Documentation/git-stash.adoc | 2 + add-interactive.c | 45 +++++++-- add-interactive.h | 17 +++- add-patch.c | 14 ++- builtin/add.c | 21 ++++- builtin/checkout.c | 31 +++++- builtin/commit.c | 16 +++- builtin/reset.c | 17 +++- builtin/stash.c | 56 ++++++++--- commit.h | 3 +- parse-options.h | 2 + t/t3701-add-interactive.sh | 119 +++++++++++++++++++----- t/t4055-diff-context.sh | 42 ++++----- t/t9902-completion.sh | 2 + 20 files changed, 324 insertions(+), 83 deletions(-)create mode 100644
Documentation/diff-context-options.adocbase-commit:
cf6f63ea6bf35173e02e18bdc6a4ba41288acff9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1915%2FNinjaInShade%2Finteractive-patch-context-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1915/NinjaInShade/interactive-patch-context-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/1915Range-diff vs v4:
1: bbb2bc7082b = 1: bbb2bc7082b t: use test_grep in t3701 and t4055 2: feace2d3676 = 2: feace2d3676 t: use test_config in t4055 3: 994029d6602 = 3: 994029d6602 add-patch: respect diff.context configuration 4: 2774b930406 ! 4: 9731e5b76fb add-patch: add diff.context command line overrides @@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char * OPT_SET_INT_F('4', "ipv4", (v), N_("use IPv4 addresses only"), \ ## t/t3701-add-interactive.sh ## -@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' - test_cmp expect actual +@@ t/t3701-add-interactive.sh: test_expect_success 'add -p rejects negative diff.context' ' + test_grep "diff.context cannot be negative" output ' --test_expect_success 'add -p respects diff.context' ' -- test_write_lines a b c d e f g h i j k l m >file && +for cmd in add checkout restore 'commit -m file' +do + test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" ' @@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff. + test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file && + git commit -m file file && + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && - git add file && -- test_write_lines a b c d e f G h i j k l m >file && -- echo y | git -c diff.context=5 add -p >actual && -- test_grep "@@ -2,11 +2,11 @@" actual ++ git add file && + echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ + reset -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual - ' - --test_expect_success 'add -p respects diff.interHunkContext' ' -- test_write_lines a b c d e f g h i j k l m n o p q r s >file && -- git add file && -- test_write_lines a b c d E f g i i j k l m N o p q r s >file && -- echo y | git -c diff.interhunkcontext=2 add -p >actual && -- test_grep "@@ -2,16 +2,16 @@" actual ++' ++ +test_expect_success 'stash accepts -U and --inter-hunk-context' ' + test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file && + git commit -m file file && @@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff. + echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \ + stash -p -U 4 --inter-hunk-context 2 >actual && + test_grep "@@ -2,20 +2,20 @@" actual - ' - --test_expect_success 'add -p rejects negative diff.context' ' -- test_config diff.context -1 && -- test_must_fail git add -p 2>output && -- test_grep "diff.context cannot be negative" output --' ++' ++ +for cmd in add checkout commit reset restore "stash save" "stash push" +do + test_expect_success "$cmd rejects invalid context options" ' @@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff. + test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual + ' +done - - test_done - - ## t/t4055-diff-context.sh ## -@@ t/t4055-diff-context.sh: test_expect_success 'The -U option overrides diff.context' ' - test_grep ! "^ firstline" output - ' - -+test_expect_success 'The -U option overrides diff.context for "add"' ' -+ test_config diff.context 8 && -+ git add -U4 -p >output && -+ test_grep ! "^ firstline" output -+' -+ -+test_expect_success 'The -U option overrides diff.context for "commit"' ' -+ test_config diff.context 8 && -+ ! git commit -U4 -p >output && -+ test_grep ! "^ firstline" output -+' -+ -+test_expect_success 'The -U option overrides diff.context for "checkout"' ' -+ test_config diff.context 8 && -+ git checkout -U4 -p >output && -+ test_grep ! "^ firstline" output -+' + -+test_expect_success 'The -U option overrides diff.context for "stash"' ' -+ test_config diff.context 8 && -+ ! git stash -U4 -p >output && -+ test_grep ! "^ firstline" output -+' -+ -+test_expect_success 'The -U option overrides diff.context for "restore"' ' -+ test_config diff.context 8 && -+ git restore -U4 -p >output && -+ test_grep ! "^ firstline" output -+' -+ - test_expect_success 'diff.context honored by "diff"' ' - test_config diff.context 8 && - git diff >output && + test_done ## t/t9902-completion.sh ## @@ t/t9902-completion.sh: test_expect_success 'double dash "git checkout"' '
Quoted 5 lines · Phillip Wood
Hi Leon
The range-diff below looks good to me. Thanks for working on this
Phillip
Yeah, the new one matches the previous one plus your fixes to the tests, which I agree with fully.
Will queue. Let's mark the topic for 'next'.
Thanks, both of you.
Great! Thanks Philip, Junio and everyone else who helped me get this finished and in.
Was a good experience :)