From 5adbabbba65bbcfa8f8feac02268e90f992ba9f4 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 23 Mar 2019 15:42:52 +0100 Subject: [PATCH] built-in add -p: handle diff.algorithm The Perl version of `git add -p` reads the config setting `diff.algorithm` and if set, uses it to generate the diff using the specified algorithm. This patch ports that functionality to the C version. To make sure that this works as intended, we add a regression test case that tries to specify a bogus diff algorithm and then verifies that `git diff-files` produced the expected error message. Note: In that new test case, we actually ignore the exit code of `git add -p`. The reason is that the C version exits with failure (as one might expect), but the Perl version does not. In fact, the Perl version continues happily after the uncolored diff failed, trying to generate the colored diff, still not catching the problem, and then it pretends to have succeeded (with exit code 0). This is arguably a bug in the Perl version, and fixing it is safely outside the scope of this patch. Signed-off-by: Johannes Schindelin --- add-interactive.c | 5 +++++ add-interactive.h | 2 +- add-patch.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/add-interactive.c b/add-interactive.c index 1786ea29c4..9e4bcb382c 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -56,11 +56,16 @@ void init_add_i_state(struct add_i_state *s, struct repository *r) FREE_AND_NULL(s->interactive_diff_filter); git_config_get_string("interactive.difffilter", &s->interactive_diff_filter); + + FREE_AND_NULL(s->interactive_diff_algorithm); + git_config_get_string("diff.algorithm", + &s->interactive_diff_algorithm); } void clear_add_i_state(struct add_i_state *s) { FREE_AND_NULL(s->interactive_diff_filter); + FREE_AND_NULL(s->interactive_diff_algorithm); memset(s, 0, sizeof(*s)); s->use_color = -1; } diff --git a/add-interactive.h b/add-interactive.h index 46c73867ad..923efaf527 100644 --- a/add-interactive.h +++ b/add-interactive.h @@ -16,7 +16,7 @@ struct add_i_state { char file_old_color[COLOR_MAXLEN]; char file_new_color[COLOR_MAXLEN]; - char *interactive_diff_filter; + char *interactive_diff_filter, *interactive_diff_algorithm; }; void init_add_i_state(struct add_i_state *s, struct repository *r); diff --git a/add-patch.c b/add-patch.c index 78bde41df0..8f2ee8688b 100644 --- a/add-patch.c +++ b/add-patch.c @@ -360,6 +360,7 @@ static int is_octal(const char *p, size_t len) static int parse_diff(struct add_p_state *s, const struct pathspec *ps) { struct argv_array args = ARGV_ARRAY_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'; @@ -369,6 +370,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) int res; argv_array_pushv(&args, s->mode->diff_cmd); + if (diff_algorithm) + argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm); if (s->revision) { struct object_id oid; argv_array_push(&args,