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

[PATCH v3 18/22] xdiff-interface: allow early return from xdiff_emit_line_fn

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Apr 12, 2021, 17:15 UTC
Message-ID
<patch-18.22-76d667f152f-20210412T170457Z-avarab@gmail.com>
In-Reply-To
<cover-00.22-00000000000-20210412T170457Z-avarab@gmail.com>

Finish the change started in the preceding commit and allow an early return from "xdiff_emit_line_fn" callbacks, this will allows diffcore-pickaxe.c to save itself redundant work.

Our xdiff interface also had the limitation of not being able to abort early since the beginning, see d9ea73e0564 (combine-diff: refactor built-in xdiff interface., 2006-04-05). Although at that time "xdiff_emit_line_fn" was called "xdiff_emit_consume_fn", and "xdiff_emit_hunk_fn" didn't exist yet.

There was some work in this area of xdiff-interface.[ch] recently with 3b40a090fd4 (diff: avoid generating unused hunk header lines, 2018-11-02) and 7c61e25fbf1 (diff: use hunk callback for word-diff, 2018-11-02).

In combination those two changes allow us to not do any work on the hunks and diff at all, but didn't change the status quo with regards to consumers that e.g. want the diff lines, but might want to abort early.

Whereas now we can abort e.g. on the first "-line" of a 1000 line diff if that's all we needed.

This interface is rather scary as noted in the comment to xdiff-interface.h being added here, as noted there a future change could add more exit codes, and hack xdl_emit_diff() and friends to ignore or skip things more selectively as a result.

I did not see an inherent reason for why xdl_emit_{diffrec,record}() could not be changed to ferry the "xdiff_emit_line_fn" error code upwards instead of returning -1 on all "ret < 0".

But doing so would require corresponding changes in xdl_emit_diff(), xdl_diff(). I didn't see any issue with narrowly doing that to accomplish what I needed here, but it would leave xdiff's own return values in an inconsistent state.

Instead I've left it at returning a more conventional (for git's own codebase) 1 for an early return, and translating it (or rather, all non-zero) to -1 for xdiff's consumption.

The reason for most of the "stop" complexity in xdiff_outf() is because we want to be able to abort early, but do so in a way that doesn't skip the appropriate strbuf_reset() invocations.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 xdiff-interface.c | 18 ++++++++++++++----
 xdiff-interface.h | 17 +++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 5d8c8c67dc2..50c0ef759dd 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -37,9 +37,12 @@ static int consume_one(void *priv_, char *s, unsigned long size)
 	char *ep;
 	while (size) {
 		unsigned long this_size;
+		int ret;
 		ep = memchr(s, '\n', size);
 		this_size = (ep == NULL) ? size : (ep - s + 1);
-		priv->line_fn(priv->consume_callback_data, s, this_size);
+		ret = priv->line_fn(priv->consume_callback_data, s, this_size);
+		if (ret)
+			return ret;
 		size -= this_size;
 		s += this_size;
 	}
@@ -50,11 +53,14 @@ static int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
 {
 	struct xdiff_emit_state *priv = priv_;
 	int i;
+	int stop = 0;
 
 	if (!priv->line_fn)
 		return 0;
 
 	for (i = 0; i < nbuf; i++) {
+		if (stop)
+			return 1;
 		if (mb[i].ptr[mb[i].size-1] != '\n') {
 			/* Incomplete line */
 			strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);
@@ -63,17 +69,21 @@ static int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
 
 		/* we have a complete line */
 		if (!priv->remainder.len) {
-			consume_one(priv, mb[i].ptr, mb[i].size);
+			stop = consume_one(priv, mb[i].ptr, mb[i].size);
 			continue;
 		}
 		strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);
-		consume_one(priv, priv->remainder.buf, priv->remainder.len);
+		stop = consume_one(priv, priv->remainder.buf, priv->remainder.len);
 		strbuf_reset(&priv->remainder);
 	}
+	if (stop)
+		return -1;
 	if (priv->remainder.len) {
-		consume_one(priv, priv->remainder.buf, priv->remainder.len);
+		stop = consume_one(priv, priv->remainder.buf, priv->remainder.len);
 		strbuf_reset(&priv->remainder);
 	}
+	if (stop)
+		return -1;
 	return 0;
 }
 
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 0198f9632f5..7d1724abb64 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -11,6 +11,23 @@
  */
 #define MAX_XDIFF_SIZE (1024UL * 1024 * 1023)
 
+/**
+ * The `xdiff_emit_line_fn` function can return 1 to abort early, or 0
+ * to continue processing. Note that doing so is an all-or-nothing
+ * affair, as returning 1 will return all the way to the top-level,
+ * e.g. the xdi_diff_outf() call to generate the diff.
+ *
+ * Thus returning 1 means you won't be getting any more diff lines. If
+ * you need something in-between those two options you'll to use
+ * `xdl_emit_hunk_consume_func_t` and implement your own version of
+ * xdl_emit_diff().
+ *
+ * We may extend the interface in the future to understand other more
+ * granular return values. While you should return 1 to exit early,
+ * doing so will currently make your early return indistinguishable
+ * from an error internal to xdiff, xdiff itself will see that
+ * non-zero return and translate it to -1.
+ */
 typedef int (*xdiff_emit_line_fn)(void *, char *, unsigned long);
 typedef void (*xdiff_emit_hunk_fn)(void *data,
 				   long old_begin, long old_nr,
-- 
2.31.1.639.g3d04783866f
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 58 of 99 in “grep: PCREv2 fixes, remove kwset.[ch]”
  1. 00/25 grep: PCREv2 fixes, remove kwset.[ch]Ævar Arnfjörð Bjarmason, Feb 3, 2021
  2. 01/25 grep/pcre2 tests: reword comments referring to kwsetÆvar Arnfjörð Bjarmason, Feb 3, 2021
  3. 03/25 grep/pcre2: drop needless assignment to NULLÆvar Arnfjörð Bjarmason, Feb 3, 2021
  4. 02/25 grep/pcre2: drop needless assignment + assert() on opt->pcre2Ævar Arnfjörð Bjarmason, Feb 3, 2021
  5. 04/25 grep/pcre2: correct reference to grep_init() in commentÆvar Arnfjörð Bjarmason, Feb 3, 2021
  6. 05/25 grep/pcre2: prepare to add debugging to pcre2_malloc()Ævar Arnfjörð Bjarmason, Feb 3, 2021
  7. 06/25 grep/pcre2: add GREP_PCRE2_DEBUG_MALLOC debug modeÆvar Arnfjörð Bjarmason, Feb 3, 2021
  8. 07/25 grep/pcre2: use compile-time PCREv2 version testÆvar Arnfjörð Bjarmason, Feb 3, 2021
  9. 08/25 grep/pcre2: use pcre2_maketables_free() functionÆvar Arnfjörð Bjarmason, Feb 3, 2021
  10. 09/25 grep/pcre2: actually make pcre2 use custom allocatorÆvar Arnfjörð Bjarmason, Feb 3, 2021
  11. 10/25 grep/pcre2: move back to thread-only PCREv2 structuresÆvar Arnfjörð Bjarmason, Feb 3, 2021
  12. 12/25 pickaxe tests: refactor to use test_commit --appendÆvar Arnfjörð Bjarmason, Feb 3, 2021
  13. 11/25 grep/pcre2: move definitions of pcre2_{malloc,free}Ævar Arnfjörð Bjarmason, Feb 3, 2021
  14. 13/25 pickaxe -S: support content with NULs under --pickaxe-regexÆvar Arnfjörð Bjarmason, Feb 3, 2021
  15. 14/25 pickaxe -S: remove redundant "sz" check in while-loopÆvar Arnfjörð Bjarmason, Feb 3, 2021
  16. René ScharfeFeb 4, 2021
  17. Junio C HamanoFeb 4, 2021
  18. Ævar Arnfjörð BjarmasonFeb 4, 2021
  19. 16/25 pickaxe tests: add test for diffgrep_consume() internalsÆvar Arnfjörð Bjarmason, Feb 3, 2021
  20. 18/25 perf: add performance test for pickaxeÆvar Arnfjörð Bjarmason, Feb 3, 2021
  21. 20/25 grep.h: make patmatch() a public functionÆvar Arnfjörð Bjarmason, Feb 3, 2021
  22. 23/25 xdiff-interface: allow early return from xdiff_emit_{line,hunk}_fnÆvar Arnfjörð Bjarmason, Feb 3, 2021
  23. 24/25 xdiff-interface: support early exit in xdiff_outf()Ævar Arnfjörð Bjarmason, Feb 3, 2021
  24. Junio C HamanoFeb 4, 2021
  25. 17/25 pickaxe tests: add test for "log -S" not being a regexÆvar Arnfjörð Bjarmason, Feb 3, 2021
  26. 19/25 pickaxe -G: set -U0 for diff generationÆvar Arnfjörð Bjarmason, Feb 3, 2021
  27. Ævar Arnfjörð BjarmasonFeb 3, 2021
  28. Junio C HamanoFeb 3, 2021
  29. 15/25 pickaxe/style: consolidate declarations and assignmentsÆvar Arnfjörð Bjarmason, Feb 3, 2021
  30. 21/25 pickaxe: use PCREv2 for -G and -SÆvar Arnfjörð Bjarmason, Feb 3, 2021
  31. Ævar Arnfjörð BjarmasonFeb 3, 2021
  32. Junio C HamanoFeb 4, 2021
  33. Junio C HamanoFeb 4, 2021
  34. 22/25 Remove unused kwset.[ch]Ævar Arnfjörð Bjarmason, Feb 3, 2021
  35. 25/25 pickaxe -G: terminate early on matching linesÆvar Arnfjörð Bjarmason, Feb 3, 2021
  36. Ævar Arnfjörð BjarmasonFeb 3, 2021
  37. 00/22 pickaxe: test and refactoring for follow-up changesÆvar Arnfjörð Bjarmason, Feb 16, 2021
  38. Junio C HamanoFeb 16, 2021
  39. Junio C HamanoFeb 17, 2021
  40. 00/22 pickaxe: test and refactoring for future PCRE backendÆvar Arnfjörð Bjarmason, Apr 12, 2021
  41. 01/22 grep/pcre2 tests: reword comments referring to kwsetÆvar Arnfjörð Bjarmason, Apr 12, 2021
  42. 02/22 pickaxe tests: refactor to use test_commit --append --printfÆvar Arnfjörð Bjarmason, Apr 12, 2021
  43. 03/22 pickaxe tests: add test for diffgrep_consume() internalsÆvar Arnfjörð Bjarmason, Apr 12, 2021
  44. 04/22 pickaxe tests: add test for "log -S" not being a regexÆvar Arnfjörð Bjarmason, Apr 12, 2021
  45. 05/22 pickaxe tests: test for -G, -S and --find-object incompatibilityÆvar Arnfjörð Bjarmason, Apr 12, 2021
  46. 06/22 pickaxe tests: add missing test for --no-pickaxe-regex being an errorÆvar Arnfjörð Bjarmason, Apr 12, 2021
  47. 07/22 pickaxe: die when -G and --pickaxe-regex are combinedÆvar Arnfjörð Bjarmason, Apr 12, 2021
  48. 08/22 pickaxe: die when --find-object and --pickaxe-all are combinedÆvar Arnfjörð Bjarmason, Apr 12, 2021
  49. 09/22 diff.h: move pickaxe fields together againÆvar Arnfjörð Bjarmason, Apr 12, 2021
  50. 10/22 pickaxe/style: consolidate declarations and assignmentsÆvar Arnfjörð Bjarmason, Apr 12, 2021
  51. 11/22 perf: add performance test for pickaxeÆvar Arnfjörð Bjarmason, Apr 12, 2021
  52. 12/22 pickaxe: refactor function selection in diffcore-pickaxe()Ævar Arnfjörð Bjarmason, Apr 12, 2021
  53. 13/22 pickaxe: assert that we must have a needle under -G or -SÆvar Arnfjörð Bjarmason, Apr 12, 2021
  54. 14/22 pickaxe -S: support content with NULs under --pickaxe-regexÆvar Arnfjörð Bjarmason, Apr 12, 2021
  55. 15/22 pickaxe: rename variables in has_changes() for brevityÆvar Arnfjörð Bjarmason, Apr 12, 2021
  56. 16/22 pickaxe -S: slightly optimize contains()Ævar Arnfjörð Bjarmason, Apr 12, 2021
  57. 17/22 xdiff-interface: prepare for allowing early returnÆvar Arnfjörð Bjarmason, Apr 12, 2021
  58. 18/22 xdiff-interface: allow early return from xdiff_emit_line_fnÆvar Arnfjörð Bjarmason, Apr 12, 2021
  59. 19/22 pickaxe -G: terminate early on matching linesÆvar Arnfjörð Bjarmason, Apr 12, 2021
  60. 20/22 pickaxe -G: don't special-case create/deleteÆvar Arnfjörð Bjarmason, Apr 12, 2021
  61. 21/22 xdiff users: use designated initializers for out_lineÆvar Arnfjörð Bjarmason, Apr 12, 2021
  62. 22/22 xdiff-interface: replace discard_hunk_line() with a flagÆvar Arnfjörð Bjarmason, Apr 12, 2021
  63. 01/22 grep/pcre2 tests: reword comments referring to kwsetÆvar Arnfjörð Bjarmason, Feb 16, 2021
  64. 02/22 test-lib-functions: document and test test_commit --no-tagÆvar Arnfjörð Bjarmason, Feb 16, 2021
  65. Junio C HamanoMar 30, 2021
  66. 03/22 test-lib-functions: reword "test_commit --append" docsÆvar Arnfjörð Bjarmason, Feb 16, 2021
  67. 04/22 test-lib functions: add --printf option to test_commitÆvar Arnfjörð Bjarmason, Feb 16, 2021
  68. Junio C HamanoMar 30, 2021
  69. Ævar Arnfjörð BjarmasonApr 12, 2021
  70. 05/22 pickaxe tests: refactor to use test_commit --append --printfÆvar Arnfjörð Bjarmason, Feb 16, 2021
  71. Junio C HamanoMar 30, 2021
  72. 06/22 pickaxe tests: add test for diffgrep_consume() internalsÆvar Arnfjörð Bjarmason, Feb 16, 2021
  73. 08/22 pickaxe tests: test for -G, -S and --find-object incompatibilityÆvar Arnfjörð Bjarmason, Feb 16, 2021
  74. Junio C HamanoMar 30, 2021
  75. 07/22 pickaxe tests: add test for "log -S" not being a regexÆvar Arnfjörð Bjarmason, Feb 16, 2021
  76. 09/22 pickaxe: die when -G and --pickaxe-regex are combinedÆvar Arnfjörð Bjarmason, Feb 16, 2021
  77. Junio C HamanoMar 30, 2021
  78. 11/22 diff.h: move pickaxe fields together againÆvar Arnfjörð Bjarmason, Feb 16, 2021
  79. 10/22 pickaxe: die when --find-object and --pickaxe-all are combinedÆvar Arnfjörð Bjarmason, Feb 16, 2021
  80. 14/22 pickaxe: refactor function selection in diffcore-pickaxe()Ævar Arnfjörð Bjarmason, Feb 16, 2021
  81. Junio C HamanoMar 30, 2021
  82. 12/22 pickaxe/style: consolidate declarations and assignmentsÆvar Arnfjörð Bjarmason, Feb 16, 2021
  83. 15/22 pickaxe: assert that we must have a needle under -G or -SÆvar Arnfjörð Bjarmason, Feb 16, 2021
  84. Junio C HamanoMar 30, 2021
  85. 17/22 pickaxe: rename variables in has_changes() for brevityÆvar Arnfjörð Bjarmason, Feb 16, 2021
  86. 13/22 perf: add performance test for pickaxeÆvar Arnfjörð Bjarmason, Feb 16, 2021
  87. 21/22 pickaxe -G: terminate early on matching linesÆvar Arnfjörð Bjarmason, Feb 16, 2021
  88. Junio C HamanoMar 31, 2021
  89. 16/22 pickaxe -S: support content with NULs under --pickaxe-regexÆvar Arnfjörð Bjarmason, Feb 16, 2021
  90. Junio C HamanoMar 30, 2021
  91. 22/22 pickaxe -G: don't special-case create/deleteÆvar Arnfjörð Bjarmason, Feb 16, 2021
  92. Junio C HamanoMar 31, 2021
  93. 18/22 pickaxe -S: slightly optimize contains()Ævar Arnfjörð Bjarmason, Feb 16, 2021
  94. Junio C HamanoMar 30, 2021
  95. 20/22 xdiff-interface: support early exit in xdiff_outf()Ævar Arnfjörð Bjarmason, Feb 16, 2021
  96. 19/22 xdiff-interface: allow early return from xdiff_emit_{line,hunk}_fnÆvar Arnfjörð Bjarmason, Feb 16, 2021
  97. Junio C HamanoMar 31, 2021
  98. Ævar Arnfjörð BjarmasonFeb 3, 2021
  99. Ævar Arnfjörð BjarmasonFeb 3, 2021

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.