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 <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2019-03-23 15:42:52 +01:00
parent e9bd93ae53
commit b47efd8bdd
3 changed files with 10 additions and 1 deletions

View File

@@ -61,6 +61,11 @@ int init_add_i_state(struct repository *r, struct add_i_state *s)
&s->interactive_diff_filter))
s->interactive_diff_filter = NULL;
free(s->interactive_diff_algorithm);
if (git_config_get_string("diff.algorithm",
&s->interactive_diff_algorithm))
s->interactive_diff_algorithm = NULL;
return 0;
}

View File

@@ -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;
};
int init_add_i_state(struct repository *r, struct add_i_state *s);
@@ -30,6 +30,7 @@ enum color_add_i {
};
const char *get_add_i_color(enum color_add_i ix);
const char *get_interactive_diff_filter(void);
const char *get_interactive_diff_algorithm(void);
struct repository;
struct pathspec;

View File

@@ -309,6 +309,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';
@@ -318,6 +319,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
int res;
argv_array_pushv(&args, s->mode->diff);
if (diff_algorithm)
argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
if (s->revision) {
struct object_id oid;
argv_array_push(&args,