From 3443546f6ef57fe28ea5cca232df8e400bfc3883 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 24 Mar 2006 20:13:22 -0800 Subject: Use a *real* built-in diff generator This uses a simplified libxdiff setup to generate unified diffs _without_ doing fork/execve of GNU "diff". This has several huge advantages, for example: Before: [torvalds@g5 linux]$ time git diff v2.6.16.. > /dev/null real 0m24.818s user 0m13.332s sys 0m8.664s After: [torvalds@g5 linux]$ time git diff v2.6.16.. > /dev/null real 0m4.563s user 0m2.944s sys 0m1.580s and the fact that this should be a lot more portable (ie we can ignore all the issues with doing fork/execve under Windows). Perhaps even more importantly, this allows us to do diffs without actually ever writing out the git file contents to a temporary file (and without any of the shell quoting issues on filenames etc etc). NOTE! THIS PATCH DOES NOT DO THAT OPTIMIZATION YET! I was lazy, and the current "diff-core" code actually will always write the temp-files, because it used to be something that you simply had to do. So this current one actually writes a temp-file like before, and then reads it into memory again just to do the diff. Stupid. But if this basic infrastructure is accepted, we can start switching over diff-core to not write temp-files, which should speed things up even further, especially when doing big tree-to-tree diffs. Now, in the interest of full disclosure, I should also point out a few downsides: - the libxdiff algorithm is different, and I bet GNU diff has gotten a lot more testing. And the thing is, generating a diff is not an exact science - you can get two different diffs (and you will), and they can both be perfectly valid. So it's not possible to "validate" the libxdiff output by just comparing it against GNU diff. - GNU diff does some nice eye-candy, like trying to figure out what the last function was, and adding that information to the "@@ .." line. libxdiff doesn't do that. - The libxdiff thing has some known deficiencies. In particular, it gets the "\No newline at end of file" case wrong. So this is currently for the experimental branch only. I hope Davide will help fix it. That said, I think the huge performance advantage, and the fact that it integrates better is definitely worth it. But it should go into a development branch at least due to the missing newline issue. Technical note: this is based on libxdiff-0.17, but I did some surgery to get rid of the extraneous fat - stuff that git doesn't need, and seriously cutting down on mmfile_t, which had much more capabilities than the diff algorithm either needed or used. In this version, "mmfile_t" is just a trivial tuple. That said, I tried to keep the differences to simple removals, so that you can do a diff between this and the libxdiff origin, and you'll basically see just things getting deleted. Even the mmfile_t simplifications are left in a state where the diffs should be readable. Apologies to Davide, whom I'd love to get feedback on this all from (I wrote my own "fill_mmfile()" for the new simpler mmfile_t format: the old complex format had a helper function for that, but I did my surgery with the goal in mind that eventually we _should_ just do mmfile_t mf; buf = read_sha1_file(sha1, type, &size); mf->ptr = buf; mf->size = size; .. use "mf" directly .. which was really a nightmare with the old "helpful" mmfile_t, and really is that easy with the new cut-down interfaces). [ Btw, as any hawk-eye can see from the diff, this was actually generated with itself, so it is "self-hosting". That's about all the testing it has gotten, along with the above kernel diff, which eye-balls correctly, but shows the newline issue when you double-check it with "git-apply" ] Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 xdiff/xemit.c (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c new file mode 100644 index 0000000000..2e5d54cfcf --- /dev/null +++ b/xdiff/xemit.c @@ -0,0 +1,141 @@ +/* + * LibXDiff by Davide Libenzi ( File Differential Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#include "xinclude.h" + + + + +static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec); +static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb); +static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg); + + + + +static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) { + + *rec = xdf->recs[ri]->ptr; + + return xdf->recs[ri]->size; +} + + +static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) { + long size, psize = strlen(pre); + char const *rec; + + size = xdl_get_rec(xdf, ri, &rec); + if (xdl_emit_diffrec(rec, size, pre, psize, ecb) < 0) { + + return -1; + } + + return 0; +} + + +/* + * Starting at the passed change atom, find the latest change atom to be included + * inside the differential hunk according to the specified configuration. + */ +static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { + xdchange_t *xch, *xchp; + + for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next) + if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen) + break; + + return xchp; +} + + +int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, + xdemitconf_t const *xecfg) { + long s1, s2, e1, e2, lctx; + xdchange_t *xch, *xche; + + for (xch = xche = xscr; xch; xch = xche->next) { + xche = xdl_get_hunk(xch, xecfg); + + s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); + s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); + + lctx = xecfg->ctxlen; + lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1)); + lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2)); + + e1 = xche->i1 + xche->chg1 + lctx; + e2 = xche->i2 + xche->chg2 + lctx; + + /* + * Emit current hunk header. + */ + if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, ecb) < 0) + return -1; + + /* + * Emit pre-context. + */ + for (; s1 < xch->i1; s1++) + if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0) + return -1; + + for (s1 = xch->i1, s2 = xch->i2;; xch = xch->next) { + /* + * Merge previous with current change atom. + */ + for (; s1 < xch->i1 && s2 < xch->i2; s1++, s2++) + if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0) + return -1; + + /* + * Removes lines from the first file. + */ + for (s1 = xch->i1; s1 < xch->i1 + xch->chg1; s1++) + if (xdl_emit_record(&xe->xdf1, s1, "-", ecb) < 0) + return -1; + + /* + * Adds lines from the second file. + */ + for (s2 = xch->i2; s2 < xch->i2 + xch->chg2; s2++) + if (xdl_emit_record(&xe->xdf2, s2, "+", ecb) < 0) + return -1; + + if (xch == xche) + break; + s1 = xch->i1 + xch->chg1; + s2 = xch->i2 + xch->chg2; + } + + /* + * Emit post-context. + */ + for (s1 = xche->i1 + xche->chg1; s1 < e1; s1++) + if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0) + return -1; + } + + return 0; +} + -- cgit v1.2.3 From acb725772964ee11656543a28c303e9aa6d092c5 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Tue, 28 Mar 2006 03:23:31 +0100 Subject: xdiff: Show function names in hunk headers. The speed of the built-in diff generator is nice; but the function names shown by `diff -p' are /really/ nice. And I hate having to choose. So, we hack xdiff to find the function names and print them. xdiff has grown a flag to say whether to dig up the function names. The builtin_diff function passes this flag unconditionally. I suppose it could parse GIT_DIFF_OPTS, but it doesn't at the moment. I've also reintroduced the `function name' into the test suite, from which it was removed in commit 3ce8f089. The function names are parsed by a particularly stupid algorithm at the moment: it just tries to find a line in the `old' file, from before the start of the hunk, whose first character looks plausible. Still, it's most definitely a start. Signed-off-by: Mark Wooding Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 2e5d54cfcf..ad5bfb1910 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -69,10 +69,43 @@ static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { } +static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { + + /* + * Be quite stupid about this for now. Find a line in the old file + * before the start of the hunk (and context) which starts with a + * plausible character. + */ + + const char *rec; + long len; + + *ll = 0; + while (i-- > 0) { + len = xdl_get_rec(xf, i, &rec); + if (len > 0 && + (isalpha((unsigned char)*rec) || /* identifier? */ + *rec == '_' || /* also identifier? */ + *rec == '(' || /* lisp defun? */ + *rec == '#')) { /* #define? */ + if (len > sz) + len = sz; + if (len && rec[len - 1] == '\n') + len--; + memcpy(buf, rec, len); + *ll = len; + return; + } + } +} + + int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { long s1, s2, e1, e2, lctx; xdchange_t *xch, *xche; + char funcbuf[40]; + long funclen = 0; for (xch = xche = xscr; xch; xch = xche->next) { xche = xdl_get_hunk(xch, xecfg); @@ -90,7 +123,13 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, /* * Emit current hunk header. */ - if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, ecb) < 0) + + if (xecfg->flags & XDL_EMIT_FUNCNAMES) { + xdl_find_func(&xe->xdf1, s1, funcbuf, + sizeof(funcbuf), &funclen); + } + if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, + funcbuf, funclen, ecb) < 0) return -1; /* -- cgit v1.2.3 From a9ed376b158faf82d3685b51d546ccaeda716da3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 28 Jun 2006 21:57:12 -0700 Subject: xdiff: generate "anti-diffs" aka what is common to two files This fairly trivial patch adds a new XDL_EMIT_xxx flag to tell libxdiff that we don't want to generate the _diff_ between two files, we want to see the lines that are _common_ to two files. So when you set XDL_EMIT_COMMON, xdl_diff() will do everything exactly like it used to do, but the output records it generates just contain the lines that aren't part of the diff. This is for doing things like generating the common base case for a file that was added in both branches. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index ad5bfb1910..714c563547 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -100,6 +100,21 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { } +int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, + xdemitconf_t const *xecfg) { + xdfile_t *xdf = &xe->xdf1; + const char *rchg = xdf->rchg; + long ix; + + for (ix = 0; ix < xdf->nrec; ix++) { + if (rchg[ix]) + continue; + if (xdl_emit_record(xdf, ix, "", ecb)) + return -1; + } + return 0; +} + int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { long s1, s2, e1, e2, lctx; @@ -107,6 +122,9 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, char funcbuf[40]; long funclen = 0; + if (xecfg->flags & XDL_EMIT_COMMON) + return xdl_emit_common(xe, xscr, ecb, xecfg); + for (xch = xche = xscr; xch; xch = xche->next) { xche = xdl_get_hunk(xch, xecfg); -- cgit v1.2.3 From 67aef034551aed0cc417e8b758a59b9978c4f3f1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 23 Oct 2006 22:22:25 +0200 Subject: xdiff/xemit.c (xdl_find_func): Elide trailing white space in a context header. This removes trailing blanks from git-generated diff headers the same way a similar patch did that for GNU diff: http://article.gmane.org/gmane.comp.gnu.utils.bugs/13839 That is, it removes trailing blanks on the hunk header line that shows the function name. Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 714c563547..154c26fdcd 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -90,7 +90,7 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { *rec == '#')) { /* #define? */ if (len > sz) len = sz; - if (len && rec[len - 1] == '\n') + while (0 < len && isspace((unsigned char)rec[len - 1])) len--; memcpy(buf, rec, len); *ll = len; -- cgit v1.2.3 From 70da769a4607dbbc4efc490287ead98175cf622b Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Wed, 25 Oct 2006 02:28:55 +0200 Subject: xdiff: Match GNU diff behaviour when deciding hunk comment worthiness of lines This removes the '#' and '(' tests and adds a '$' test instead although I have no idea what it is actually good for - but hey, if that's what GNU diff does... Pasky only went and did as Junio sayeth. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 154c26fdcd..07995ec33e 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -86,8 +86,7 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { if (len > 0 && (isalpha((unsigned char)*rec) || /* identifier? */ *rec == '_' || /* also identifier? */ - *rec == '(' || /* lisp defun? */ - *rec == '#')) { /* #define? */ + *rec == '$')) { /* mysterious GNU diff's invention */ if (len > sz) len = sz; while (0 < len && isspace((unsigned char)rec[len - 1])) -- cgit v1.2.3 From f73da29fa2be2f4bbda86e006b743b8121bdbf19 Mon Sep 17 00:00:00 2001 From: Andy Parkins Date: Thu, 23 Nov 2006 10:05:17 +0000 Subject: Increase length of function name buffer In xemit.c:xdl_emit_diff() a buffer for showing the function name as commentary is allocated; this buffer was 40 characters. This is a bit small; particularly for C++ function names where there is often an identical prefix (like void LongNamespace::LongClassName) on multiple functions, which makes the context the same everywhere. In other words the context is useless. This patch increases that buffer to 80 characters - which may still not be enough, but is better Signed-off-by: Andy Parkins Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 07995ec33e..e291dc7608 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -118,7 +118,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { long s1, s2, e1, e2, lctx; xdchange_t *xch, *xche; - char funcbuf[40]; + char funcbuf[80]; long funclen = 0; if (xecfg->flags & XDL_EMIT_COMMON) -- cgit v1.2.3 From a6080a0a44d5ead84db3dabbbc80e82df838533d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 7 Jun 2007 00:04:01 -0700 Subject: War on whitespace This uses "git-apply --whitespace=strip" to fix whitespace errors that have crept in to our source files over time. There are a few files that need to have trailing whitespaces (most notably, test vectors). The results still passes the test, and build result in Documentation/ area is unchanged. Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index e291dc7608..78b1d4b8bb 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -194,4 +194,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, return 0; } - -- cgit v1.2.3 From 52fae7de4e8455dad048f1b8a645729571c42848 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 7 Jun 2007 22:45:00 +0200 Subject: Missing statics. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 78b1d4b8bb..4b6e639112 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -99,8 +99,8 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { } -int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, - xdemitconf_t const *xecfg) { +static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, + xdemitconf_t const *xecfg) { xdfile_t *xdf = &xe->xdf1; const char *rchg = xdf->rchg; long ix; -- cgit v1.2.3 From f258475a6ede3617ae768b69e33f78cbab8312de Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 6 Jul 2007 00:45:10 -0700 Subject: Per-path attribute based hunk header selection. This makes"diff -p" hunk headers customizable via gitattributes mechanism. It is based on Johannes's earlier patch that allowed to define a single regexp to be used for everything. The mechanism to arrive at the regexp that is used to define hunk header is the same as other use of gitattributes. You assign an attribute, funcname (because "diff -p" typically uses the name of the function the patch is about as the hunk header), a simple string value. This can be one of the names of built-in pattern (currently, "java" is defined) or a custom pattern name, to be looked up from the configuration file. (in .gitattributes) *.java funcname=java *.perl funcname=perl (in .git/config) [funcname] java = ... # ugly and complicated regexp to override the built-in one. perl = ... # another ugly and complicated regexp to define a new one. Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 4b6e639112..d3d9c845c6 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -69,7 +69,24 @@ static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { } -static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { +static long def_ff(const char *rec, long len, char *buf, long sz, void *priv) +{ + if (len > 0 && + (isalpha((unsigned char)*rec) || /* identifier? */ + *rec == '_' || /* also identifier? */ + *rec == '$')) { /* identifiers from VMS and other esoterico */ + if (len > sz) + len = sz; + while (0 < len && isspace((unsigned char)rec[len - 1])) + len--; + memcpy(buf, rec, len); + return len; + } + return -1; +} + +static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll, + find_func_t ff, void *ff_priv) { /* * Be quite stupid about this for now. Find a line in the old file @@ -80,22 +97,12 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { const char *rec; long len; - *ll = 0; while (i-- > 0) { len = xdl_get_rec(xf, i, &rec); - if (len > 0 && - (isalpha((unsigned char)*rec) || /* identifier? */ - *rec == '_' || /* also identifier? */ - *rec == '$')) { /* mysterious GNU diff's invention */ - if (len > sz) - len = sz; - while (0 < len && isspace((unsigned char)rec[len - 1])) - len--; - memcpy(buf, rec, len); - *ll = len; + if ((*ll = ff(rec, len, buf, sz, ff_priv)) >= 0) return; - } } + *ll = 0; } @@ -120,6 +127,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdchange_t *xch, *xche; char funcbuf[80]; long funclen = 0; + find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff; if (xecfg->flags & XDL_EMIT_COMMON) return xdl_emit_common(xe, xscr, ecb, xecfg); @@ -143,7 +151,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, if (xecfg->flags & XDL_EMIT_FUNCNAMES) { xdl_find_func(&xe->xdf1, s1, funcbuf, - sizeof(funcbuf), &funclen); + sizeof(funcbuf), &funclen, + ff, xecfg->find_func_priv); } if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, funcbuf, funclen, ecb) < 0) -- cgit v1.2.3 From ef2e62fe23173586f49a00c6ae953ebbdb0d13ab Mon Sep 17 00:00:00 2001 From: Brian Downing Date: Sat, 25 Oct 2008 15:30:54 +0200 Subject: Allow alternate "low-level" emit function from xdl_diff For some users (e.g. git blame), getting textual patch output is just extra work, as they can get all the information they need from the low- level diff structures. Allow for an alternate low-level emit function to be defined to allow bypassing the textual patch generation; set xemitconf_t's emit_func member to enable this. The (void (*)()) type is pretty ugly, but the alternative would be to include most of the private xdiff headers in xdiff.h to get the types required for the "proper" function prototype. Also, a (void *) won't work, as ANSI C doesn't allow a function pointer to be cast to an object pointer. Signed-off-by: Brian Downing Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index d3d9c845c6..4625c1b421 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -27,7 +27,6 @@ static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec); static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb); -static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg); @@ -58,7 +57,7 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t * * Starting at the passed change atom, find the latest change atom to be included * inside the differential hunk according to the specified configuration. */ -static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { +xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { xdchange_t *xch, *xchp; for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next) -- cgit v1.2.3 From 6d0e674a575421347abe5749e645ca6dc78c8207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sun, 28 Dec 2008 19:45:32 +0100 Subject: diff: add option to show context between close hunks Merge two hunks if there is only the specified number of otherwise unshown context between them. For --inter-hunk-context=1, the resulting patch has the same number of lines but shows uninterrupted context instead of a context header line in between. Patches generated with this option are easier to read but are also more likely to conflict if the file to be patched contains other changes. This patch keeps the default for this option at 0. It is intended to just make the feature available in order to see its advantages and downsides. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 4625c1b421..05bfa41f10 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -59,9 +59,10 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t * */ xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { xdchange_t *xch, *xchp; + long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next) - if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen) + if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common) break; return xchp; -- cgit v1.2.3 From 8e24cbaeafc7eed709e251fda1673ffea84edfb1 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sun, 15 Mar 2009 22:01:20 +0100 Subject: Fix various dead stores found by the clang static analyzer http-push.c::finish_request(): request is initialized by the for loop index-pack.c::free_base_data(): b is initialized by the for loop merge-recursive.c::process_renames(): move compare to narrower scope, and remove unused assignments to it remove unused variable renames2 xdiff/xdiffi.c::xdl_recs_cmp(): remove unused variable ec xdiff/xemit.c::xdl_emit_diff(): xche is always overwritten Signed-off-by: Benjamin Kramer Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 05bfa41f10..c4bedf0d1c 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -132,7 +132,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, if (xecfg->flags & XDL_EMIT_COMMON) return xdl_emit_common(xe, xscr, ecb, xecfg); - for (xch = xche = xscr; xch; xch = xche->next) { + for (xch = xscr; xch; xch = xche->next) { xche = xdl_get_hunk(xch, xecfg); s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); -- cgit v1.2.3 From c099789bb01b810e40f9cfaa5c842ed568110fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sun, 26 Sep 2010 18:26:56 +0200 Subject: diff: avoid repeated scanning while looking for funcname MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For each hunk, xdl_find_func searches the preimage for a function name until the beginning of the file. If the file does not contain any function names, this search has complexity O(n^2) in the number of hunks n. Instead, inline xdl_find_func() and keep track of up to which line we have scanned already and the contents of the last funcname line that we have found. Noticed and a different approach proposed by Clemens Buchacher. This alternative solution was done by René Scharfe. Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'xdiff/xemit.c') diff --git a/xdiff/xemit.c b/xdiff/xemit.c index c4bedf0d1c..277e2eec5b 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -85,27 +85,6 @@ static long def_ff(const char *rec, long len, char *buf, long sz, void *priv) return -1; } -static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll, - find_func_t ff, void *ff_priv) { - - /* - * Be quite stupid about this for now. Find a line in the old file - * before the start of the hunk (and context) which starts with a - * plausible character. - */ - - const char *rec; - long len; - - while (i-- > 0) { - len = xdl_get_rec(xf, i, &rec); - if ((*ll = ff(rec, len, buf, sz, ff_priv)) >= 0) - return; - } - *ll = 0; -} - - static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { xdfile_t *xdf = &xe->xdf1; @@ -127,6 +106,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdchange_t *xch, *xche; char funcbuf[80]; long funclen = 0; + long funclineprev = -1; find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff; if (xecfg->flags & XDL_EMIT_COMMON) @@ -150,9 +130,19 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, */ if (xecfg->flags & XDL_EMIT_FUNCNAMES) { - xdl_find_func(&xe->xdf1, s1, funcbuf, - sizeof(funcbuf), &funclen, - ff, xecfg->find_func_priv); + long l; + for (l = s1 - 1; l >= 0 && l > funclineprev; l--) { + const char *rec; + long reclen = xdl_get_rec(&xe->xdf1, l, &rec); + long newfunclen = ff(rec, reclen, funcbuf, + sizeof(funcbuf), + xecfg->find_func_priv); + if (newfunclen >= 0) { + funclen = newfunclen; + break; + } + } + funclineprev = s1 - 1; } if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, funcbuf, funclen, ecb) < 0) -- cgit v1.2.3