From: Johannes Sixt <j.sixt@viscovery.net>
To: Antoine Pelisse <apelisse@gmail.com>
Cc: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH] Allow combined diff to ignore white-spaces
Date: Thu, 14 Mar 2013 08:08:35 +0100 [thread overview]
Message-ID: <51417773.5000401@viscovery.net> (raw)
In-Reply-To: <1363209683-10264-1-git-send-email-apelisse@gmail.com>
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@gmail.com>
> ---
> 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
next prev parent reply other threads:[~2013-03-14 7:09 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-02 15:04 [PATCH] Allow combined diff to ignore white-spaces Antoine Pelisse
2013-03-03 7:45 ` Junio C Hamano
2013-03-04 18:17 ` Antoine Pelisse
2013-03-04 18:36 ` Junio C Hamano
2013-03-04 18:50 ` Antoine Pelisse
2013-03-13 21:21 ` Antoine Pelisse
2013-03-13 23:42 ` Junio C Hamano
2013-03-13 23:53 ` Junio C Hamano
2013-03-14 7:08 ` Johannes Sixt [this message]
2013-03-14 15:31 ` Junio C Hamano
2013-03-14 15:51 ` Antoine Pelisse
2013-03-14 21:03 ` [PATCH v3] " Antoine Pelisse
2013-03-14 21:43 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51417773.5000401@viscovery.net \
--to=j.sixt@viscovery.net \
--cc=apelisse@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).