git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 3/3] diffcore-pickaxe: unify setup and teardown code between log -S/-G

From
Junio C Hamano <gitster@pobox.com>
Date
Apr 5, 2013, 16:44 UTC
Message-ID
<7vr4ipc4fv.fsf@alter.siamese.dyndns.org>
In-Reply-To
<20130405054524.GB12705@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I didn't actually test that patch beyond compilation (but it's
> _obviously_ correct, right?), and I'm about to go to bed. Do you want to
> take care of adapting your commit message to it?
The code looks obviously correct, yes.

We might have to revisit the "Is unmerged?" thing, Cf. d7c9bf22351e (diffcore-rename: don't consider unmerged path as source, 2011-03-23), but that is an unlikely corner case, especially for these options (-S/-G).

-- >8 --
From: Jeff King <peff@peff.net>
Date: Fri, 5 Apr 2013 01:28:10 -0400
Subject: [PATCH] diffcore-pickaxe: unify code for log -S/-G

The logic flow of has_changes() used for "log -S" and diff_grep() used for "log -G" are essentially the same. See if we have both sides that could be different in any interesting way, slurp the contents in core, possibly after applying textconv, inspect the contents, clean-up and report the result. The only difference between the two is how "inspect" step works.

Unify this codeflow in a helper, pickaxe_match(), which takes a callback function that implements the specific "inspect" step.

After removing the common scaffolding code from the existing has_changes() and diff_grep(), they each becomes such a callback function suitable for passing to pickaxe_match().

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 diffcore-pickaxe.c | 118 ++++++++++++++++++++++-------------------------------
 1 file changed, 49 insertions(+), 69 deletions(-)
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index cadb071..63722f8 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -8,7 +8,12 @@
 #include "xdiff-interface.h"
 #include "kwset.h"
 
-typedef int (*pickaxe_fn)(struct diff_filepair *p, struct diff_options *o, regex_t *regexp, kwset_t kws);
+typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
+			  struct diff_options *o,
+			  regex_t *regexp, kwset_t kws);
+
+static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
+			 regex_t *regexp, kwset_t kws, pickaxe_fn fn);
 
 static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
 		    regex_t *regexp, kwset_t kws, pickaxe_fn fn)
@@ -22,7 +27,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
 		/* Showing the whole changeset if needle exists */
 		for (i = 0; i < q->nr; i++) {
 			struct diff_filepair *p = q->queue[i];
-			if (fn(p, o, regexp, kws))
+			if (pickaxe_match(p, o, regexp, kws, fn))
 				return; /* do not munge the queue */
 		}
 
@@ -37,7 +42,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
 		/* Showing only the filepairs that has the needle */
 		for (i = 0; i < q->nr; i++) {
 			struct diff_filepair *p = q->queue[i];
-			if (fn(p, o, regexp, kws))
+			if (pickaxe_match(p, o, regexp, kws, fn))
 				diff_q(&outq, p);
 			else
 				diff_free_filepair(p);
@@ -74,64 +79,33 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
 	line[len] = hold;
 }
 
-static int diff_grep(struct diff_filepair *p, struct diff_options *o,
+static int diff_grep(mmfile_t *one, mmfile_t *two,
+		     struct diff_options *o,
 		     regex_t *regexp, kwset_t kws)
 {
 	regmatch_t regmatch;
-	struct userdiff_driver *textconv_one = NULL;
-	struct userdiff_driver *textconv_two = NULL;
-	mmfile_t mf1, mf2;
-	int hit;
+	struct diffgrep_cb ecbdata;
+	xpparam_t xpp;
+	xdemitconf_t xecfg;
 
-	if (!o->pickaxe[0])
-		return 0;
+	if (!one)
+		return !regexec(regexp, two->ptr, 1, &regmatch, 0);
+	if (!two)
+		return !regexec(regexp, one->ptr, 1, &regmatch, 0);
 
-	if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
-		textconv_one = get_textconv(p->one);
-		textconv_two = get_textconv(p->two);
-	}
-
-	if (textconv_one == textconv_two && diff_unmodified_pair(p))
-		return 0;
-
-	mf1.size = fill_textconv(textconv_one, p->one, &mf1.ptr);
-	mf2.size = fill_textconv(textconv_two, p->two, &mf2.ptr);
-
-	if (!DIFF_FILE_VALID(p->one)) {
-		if (!DIFF_FILE_VALID(p->two))
-			hit = 0; /* ignore unmerged */
-		else
-			/* created "two" -- does it have what we are looking for? */
-			hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);
-	} else if (!DIFF_FILE_VALID(p->two)) {
-		/* removed "one" -- did it have what we are looking for? */
-		hit = !regexec(regexp, mf1.ptr, 1, &regmatch, 0);
-	} else {
-		/*
-		 * We have both sides; need to run textual diff and see if
-		 * the pattern appears on added/deleted lines.
-		 */
-		struct diffgrep_cb ecbdata;
-		xpparam_t xpp;
-		xdemitconf_t xecfg;
-
-		memset(&xpp, 0, sizeof(xpp));
-		memset(&xecfg, 0, sizeof(xecfg));
-		ecbdata.regexp = regexp;
-		ecbdata.hit = 0;
-		xecfg.ctxlen = o->context;
-		xecfg.interhunkctxlen = o->interhunkcontext;
-		xdi_diff_outf(&mf1, &mf2, diffgrep_consume, &ecbdata,
-			      &xpp, &xecfg);
-		hit = ecbdata.hit;
-	}
-	if (textconv_one)
-		free(mf1.ptr);
-	if (textconv_two)
-		free(mf2.ptr);
-	diff_free_filespec_data(p->one);
-	diff_free_filespec_data(p->two);
-	return hit;
+	/*
+	 * We have both sides; need to run textual diff and see if
+	 * the pattern appears on added/deleted lines.
+	 */
+	memset(&xpp, 0, sizeof(xpp));
+	memset(&xecfg, 0, sizeof(xecfg));
+	ecbdata.regexp = regexp;
+	ecbdata.hit = 0;
+	xecfg.ctxlen = o->context;
+	xecfg.interhunkctxlen = o->interhunkcontext;
+	xdi_diff_outf(one, two, diffgrep_consume, &ecbdata,
+		      &xpp, &xecfg);
+	return ecbdata.hit;
 }
 
 static void diffcore_pickaxe_grep(struct diff_options *o)
@@ -198,9 +172,20 @@ static unsigned int contains(mmfile_t *mf, struct diff_options *o,
 	return cnt;
 }
 
-static int has_changes(struct diff_filepair *p, struct diff_options *o,
+static int has_changes(mmfile_t *one, mmfile_t *two,
+		       struct diff_options *o,
 		       regex_t *regexp, kwset_t kws)
 {
+	if (!one)
+		return contains(two, o, regexp, kws) != 0;
+	if (!two)
+		return contains(one, o, regexp, kws) != 0;
+	return contains(one, o, regexp, kws) != contains(two, o, regexp, kws);
+}
+
+static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
+			 regex_t *regexp, kwset_t kws, pickaxe_fn fn)
+{
 	struct userdiff_driver *textconv_one = NULL;
 	struct userdiff_driver *textconv_two = NULL;
 	mmfile_t mf1, mf2;
@@ -209,6 +194,10 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
 	if (!o->pickaxe[0])
 		return 0;
 
+	/* ignore unmerged */
+	if (!DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two))
+		return 0;
+
 	if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
 		textconv_one = get_textconv(p->one);
 		textconv_two = get_textconv(p->two);
@@ -227,18 +216,9 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
 	mf1.size = fill_textconv(textconv_one, p->one, &mf1.ptr);
 	mf2.size = fill_textconv(textconv_two, p->two, &mf2.ptr);
 
-	if (!DIFF_FILE_VALID(p->one)) {
-		if (!DIFF_FILE_VALID(p->two))
-			ret = 0; /* ignore unmerged */
-		else
-			/* created */
-			ret = contains(&mf2, o, regexp, kws) != 0;
-	}
-	else if (!DIFF_FILE_VALID(p->two)) /* removed */
-		ret = contains(&mf1, o, regexp, kws) != 0;
-	else
-		ret = contains(&mf1, o, regexp, kws) !=
-		      contains(&mf2, o, regexp, kws);
+	ret = fn(DIFF_FILE_VALID(p->one) ? &mf1 : NULL,
+		 DIFF_FILE_VALID(p->two) ? &mf2 : NULL,
+		 o, regexp, kws);
 
 	if (textconv_one)
 		free(mf1.ptr);
-- 
1.8.2-667-gbdcd2ef
Previous: Jeff KingNext: Simon Ruderich
Message 23 of 27 in “[BUG] git log -S not respecting --no-textconv”
  1. Matthieu MoyApr 4, 2013
  2. 1/2 diffcore-pickaxe: respect --no-textconvSimon Ruderich, Apr 4, 2013
  3. Matthieu MoyApr 4, 2013
  4. Jeff KingApr 4, 2013
  5. Junio C HamanoApr 4, 2013
  6. Jeff KingApr 4, 2013
  7. Junio C HamanoApr 4, 2013
  8. 1/3 diffcore-pickaxe: remove unnecessary call to get_textconv()Simon Ruderich, Apr 4, 2013
  9. Junio C HamanoApr 4, 2013
  10. Junio C HamanoApr 4, 2013
  11. Jeff KingApr 4, 2013
  12. Junio C HamanoApr 4, 2013
  13. Simon RuderichApr 5, 2013
  14. 2/3 diffcore-pickaxe: remove fill_one()Simon Ruderich, Apr 4, 2013
  15. Jeff KingApr 5, 2013
  16. Junio C HamanoApr 5, 2013
  17. 1/3 diffcore-pickaxe: port optimization from has_changes() to diff_grep()Junio C Hamano, Apr 5, 2013
  18. 2/3 diffcore-pickaxe: fix leaks in "log -S<block>" and "log -G<pattern>"Junio C Hamano, Apr 5, 2013
  19. 3/3 diffcore-pickaxe: unify setup and teardown code between log -S/-GJunio C Hamano, Apr 5, 2013
  20. Jeff KingApr 5, 2013
  21. Junio C HamanoApr 5, 2013
  22. Jeff KingApr 5, 2013
  23. Junio C HamanoApr 5, 2013
  24. 3/3 diffcore-pickaxe: respect --no-textconvSimon Ruderich, Apr 4, 2013
  25. Matthieu MoyApr 5, 2013
  26. 3/3 diffcore-pickaxe: respect --no-textconvSimon Ruderich, Apr 5, 2013
  27. Junio C HamanoApr 5, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.