Am 3/13/2013 22:21, schrieb Antoine Pelisse: > Currently, it's not possible to use the space-ignoring options (-b, -w, > --ignore-space-at-eol) with combined diff. It makes it pretty impossible > to read a merge between a branch that changed all tabs to spaces, and a > branch with functional changes. > > Pass diff flags to diff engine, so that combined diff behaves as normal > diff does with spaces. > Also coalesce lines that are removed from both (or more) parents. > > It also means that a conflict-less merge done using a ignore-* strategy > option will not show any conflict if shown in combined-diff using the > same option. > > Signed-off-by: Antoine Pelisse <apelisse@xxxxxxxxx> > --- > OK, I added some tests and coalesce similar lost lines (using the same flags > we used for diff. > > combine-diff.c | 57 ++++++++++++++++++++++++++++++----- > t/t4038-diff-combined.sh | 75 ++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 125 insertions(+), 7 deletions(-) > > diff --git a/combine-diff.c b/combine-diff.c > index 35d41cd..0f33983 100644 > --- a/combine-diff.c > +++ b/combine-diff.c > @@ -5,6 +5,7 @@ > #include "diffcore.h" > #include "quote.h" > #include "xdiff-interface.h" > +#include "xdiff/xmacros.h" > #include "log-tree.h" > #include "refs.h" > #include "userdiff.h" > @@ -122,7 +123,47 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode, > return blob; > } > > -static void append_lost(struct sline *sline, int n, const char *line, int len) > +static int match_string_spaces(const char *line1, int len1, > + const char *line2, int len2, > + long flags) > +{ > + if (flags & XDF_WHITESPACE_FLAGS) { > + for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--); > + for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--); > + } > + > + if (!(flags & (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE))) > + return (len1 == len2 && !memcmp(line1, line2, len1)); > + > + while (len1 > 0 && len2 > 0) { > + len1--; > + len2--; > + if (XDL_ISSPACE(line1[len1]) || XDL_ISSPACE(line2[len2])) { > + if ((flags & XDF_IGNORE_WHITESPACE_CHANGE) && > + (!XDL_ISSPACE(line1[len1]) || !XDL_ISSPACE(line2[len2]))) > + return 0; > + > + for (; len1 > 0 && XDL_ISSPACE(line1[len1]); len1--); > + for (; len2 > 0 && XDL_ISSPACE(line2[len2]); len2--); > + } > + if (line1[len1] != line2[len2]) > + return 0; > + } > + > + if (flags & XDF_IGNORE_WHITESPACE) { > + // Consume remaining spaces > + for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--); > + for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--); > + } > + > + // We matched full line1 and line2 > + if (!len1 && !len2) > + return 1; > + > + return 0; > +} > + > +static void append_lost(struct sline *sline, int n, const char *line, int len, long flags) > { > struct lline *lline; > unsigned long this_mask = (1UL<<n); > @@ -133,8 +174,8 @@ static void append_lost(struct sline *sline, int n, const char *line, int len) > if (sline->lost_head) { > lline = sline->next_lost; > while (lline) { > - if (lline->len == len && > - !memcmp(lline->line, line, len)) { > + if (match_string_spaces(lline->line, lline->len, > + line, len, flags)) { > lline->parent_map |= this_mask; > sline->next_lost = lline->next; > return; > @@ -162,6 +203,7 @@ struct combine_diff_state { > int n; > struct sline *sline; > struct sline *lost_bucket; > + long flags; > }; > > static void consume_line(void *state_, char *line, unsigned long len) > @@ -201,7 +243,7 @@ static void consume_line(void *state_, char *line, unsigned long len) > return; /* not in any hunk yet */ > switch (line[0]) { > case '-': > - append_lost(state->lost_bucket, state->n, line+1, len-1); > + append_lost(state->lost_bucket, state->n, line+1, len-1, state->flags); > break; > case '+': > state->sline[state->lno-1].flag |= state->nmask; > @@ -215,7 +257,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode, > struct sline *sline, unsigned int cnt, int n, > int num_parent, int result_deleted, > struct userdiff_driver *textconv, > - const char *path) > + const char *path, long flags) > { > unsigned int p_lno, lno; > unsigned long nmask = (1UL << n); > @@ -231,9 +273,10 @@ static void combine_diff(const unsigned char *parent, unsigned int mode, > parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path); > parent_file.size = sz; > memset(&xpp, 0, sizeof(xpp)); > - xpp.flags = 0; > + xpp.flags = flags; > memset(&xecfg, 0, sizeof(xecfg)); > memset(&state, 0, sizeof(state)); > + state.flags = flags; > state.nmask = nmask; > state.sline = sline; > state.lno = 1; > @@ -962,7 +1005,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, > elem->parent[i].mode, > &result_file, sline, > cnt, i, num_parent, result_deleted, > - textconv, elem->path); > + textconv, elem->path, opt->xdl_opts); > } > > show_hunks = make_hunks(sline, cnt, num_parent, dense); > diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh > index 614425a..ba8a56b 100755 > --- a/t/t4038-diff-combined.sh > +++ b/t/t4038-diff-combined.sh > @@ -113,4 +113,79 @@ test_expect_success 'check --cc --raw with forty trees' ' > grep "^::::::::::::::::::::::::::::::::::::::::[^:]" out > ' > > +test_expect_success 'setup combined ignore spaces' ' > + git checkout master && > + >test && > + git add test && > + git commit -m initial && > + > + echo " > + always coalesce > + eol space coalesce \n\ > + space change coalesce > + all spa ces coalesce > + eol spaces \n\ > + space change > + all spa ces" >test && This form of 'echo' is not sufficiently portable. How about: tr -d Q <<-\EOF >test && always coalesce eol space coalesce Q space change coalesce all spa ces coalesce eol spaces Q space change all spa ces EOF > + git commit -m "change three" -a && > + > + git checkout -b side HEAD^ && > + echo " > + always coalesce > + eol space coalesce > + space change coalesce > + all spaces coalesce > + eol spaces > + space change > + all spaces" >test && > + git commit -m indent -a && > + > + test_must_fail git merge master && > + echo " > + eol spaces \n\ > + space change > + all spa ces" > test && Ditto. > + git commit -m merged -a > +' > + > +test_expect_success 'check combined output (no ignore space)' ' > + git show | test_i18ngrep "^-\s*eol spaces" && > + git show | test_i18ngrep "^-\s*eol space coalesce" && > + git show | test_i18ngrep "^-\s*space change" && > + git show | test_i18ngrep "^-\s*space change coalesce" && > + git show | test_i18ngrep "^-\s*all spaces" && > + git show | test_i18ngrep "^-\s*all spaces coalesce" && > + git show | test_i18ngrep "^--\s*always coalesce" This loses the exit code of git show. We usually write this as git show >actual && grep "^- *eol spaces" && grep "^- *eol space coalesce" && ... (Same for later tests.) There is nothing i18n-ish in the test patterns. Use regular grep. BTW, there is compare_diff_patch() in diff-lib.sh. You can use it to compare diff output to expected output. Then you do not need a grep invocation for each line of the test file. -- Hannes -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html