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 <[email protected]>
> ---
> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html