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

[JGIT PATCH 14/15] Abstract the hunk header testing into a method

From
Shawn O. Pearce <spearce@spearce.org>
Date
Dec 12, 2008, 02:46 UTC
Message-ID
<1229049981-14152-15-git-send-email-spearce@spearce.org>
In-Reply-To
<1229049981-14152-14-git-send-email-spearce@spearce.org>

This way we can test for "@@@ -" and "@@@@@@@ -" for combined diffs in octopus merges. We use the same scan test for the basic two-way case, as the format is identical but has less marker characters.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/patch/FileHeader.java     |   36 +++++++++++++++++--
 .../src/org/spearce/jgit/patch/Patch.java          |    8 ++--
 2 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/patch/FileHeader.java b/org.spearce.jgit/src/org/spearce/jgit/patch/FileHeader.java
index a58e978..5fe2acf 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/patch/FileHeader.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/patch/FileHeader.java
@@ -87,8 +87,6 @@
 
 	static final byte[] NEW_NAME = encodeASCII("+++ ");
 
-	static final byte[] HUNK_HDR = encodeASCII("@@ -");
-
 	/** General type of change a single file-level patch describes. */
 	public static enum ChangeType {
 		/** Add a new file to the project */
@@ -358,7 +356,7 @@ int parseGitFileName(int ptr, final int end) {
 	int parseGitHeaders(int ptr, final int end) {
 		while (ptr < end) {
 			final int eol = nextLF(buf, ptr);
-			if (match(buf, ptr, HUNK_HDR) >= 0) {
+			if (isHunkHdr(buf, ptr, eol) >= 1) {
 				// First hunk header; break out and parse them later.
 				break;
 
@@ -432,7 +430,7 @@ int parseGitHeaders(int ptr, final int end) {
 	int parseTraditionalHeaders(int ptr, final int end) {
 		while (ptr < end) {
 			final int eol = nextLF(buf, ptr);
-			if (match(buf, ptr, HUNK_HDR) >= 0) {
+			if (isHunkHdr(buf, ptr, eol) >= 1) {
 				// First hunk header; break out and parse them later.
 				break;
 
@@ -519,4 +517,34 @@ private boolean eq(int aPtr, int aEnd, int bPtr, int bEnd) {
 		}
 		return true;
 	}
+
+	/**
+	 * Determine if this is a patch hunk header.
+	 * 
+	 * @param buf
+	 *            the buffer to scan
+	 * @param start
+	 *            first position in the buffer to evaluate
+	 * @param end
+	 *            last position to consider; usually the end of the buffer (
+	 *            <code>buf.length</code>) or the first position on the next
+	 *            line. This is only used to avoid very long runs of '@' from
+	 *            killing the scan loop.
+	 * @return the number of "ancestor revisions" in the hunk header. A
+	 *         traditional two-way diff ("@@ -...") returns 1; a combined diff
+	 *         for a 3 way-merge returns 3. If this is not a hunk header, 0 is
+	 *         returned instead.
+	 */
+	static int isHunkHdr(final byte[] buf, final int start, final int end) {
+		int ptr = start;
+		while (ptr < end && buf[ptr] == '@')
+			ptr++;
+		if (ptr - start < 2)
+			return 0;
+		if (ptr == end || buf[ptr++] != ' ')
+			return 0;
+		if (ptr == end || buf[ptr++] != '-')
+			return 0;
+		return (ptr - 3) - start;
+	}
 }
diff --git a/org.spearce.jgit/src/org/spearce/jgit/patch/Patch.java b/org.spearce.jgit/src/org/spearce/jgit/patch/Patch.java
index 9aca22d..e1e79b7 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/patch/Patch.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/patch/Patch.java
@@ -38,7 +38,7 @@
 package org.spearce.jgit.patch;
 
 import static org.spearce.jgit.lib.Constants.encodeASCII;
-import static org.spearce.jgit.patch.FileHeader.HUNK_HDR;
+import static org.spearce.jgit.patch.FileHeader.isHunkHdr;
 import static org.spearce.jgit.patch.FileHeader.NEW_NAME;
 import static org.spearce.jgit.patch.FileHeader.OLD_NAME;
 import static org.spearce.jgit.util.RawParseUtils.match;
@@ -162,7 +162,7 @@ public void parse(final byte[] buf, int ptr, final int end) {
 
 	private int parseFile(final byte[] buf, int c, final int end) {
 		while (c < end) {
-			if (match(buf, c, HUNK_HDR) >= 0) {
+			if (isHunkHdr(buf, c, end) >= 1) {
 				// If we find a disconnected hunk header we might
 				// have missed a file header previously. The hunk
 				// isn't valid without knowing where it comes from.
@@ -205,7 +205,7 @@ private int parseFile(final byte[] buf, int c, final int end) {
 				final int f = nextLF(buf, n);
 				if (f >= end)
 					return end;
-				if (match(buf, f, HUNK_HDR) >= 0)
+				if (isHunkHdr(buf, f, end) == 1)
 					return parseTraditionalPatch(buf, c, end);
 			}
 
@@ -274,7 +274,7 @@ private int parseHunks(final FileHeader fh, int c, final int end) {
 			if (match(buf, c, NEW_NAME) >= 0)
 				break;
 
-			if (match(buf, c, HUNK_HDR) >= 0) {
+			if (isHunkHdr(buf, c, end) == 1) {
 				final HunkHeader h = new HunkHeader(fh, c);
 				h.parseHeader(end);
 				c = h.parseBody(this, end);
-- 
1.6.1.rc2.306.ge5d5e
Previous: Shawn O. PearceNext: Shawn O. Pearce
Message 15 of 22 in “More patch parsing support”
  1. 00/15 More patch parsing supportShawn O. Pearce, Dec 12, 2008
  2. 01/15 Correct use of TemporaryBuffer in PatchShawn O. Pearce, Dec 12, 2008
  3. 02/15 Add tests for TemporaryBufferShawn O. Pearce, Dec 12, 2008
  4. 03/15 Add IntList as a more efficient representation of List<Integer>Shawn O. Pearce, Dec 12, 2008
  5. 04/15 Add lineMap computer to RawParseUtils to index locations of line startsShawn O. Pearce, Dec 12, 2008
  6. 05/15 Define FileHeader.PatchType to report the style of patch usedShawn O. Pearce, Dec 12, 2008
  7. 06/15 Test for non-git binary files and mark them as PatchType.BINARYShawn O. Pearce, Dec 12, 2008
  8. 07/15 Set empty patches with no Git metadata to PatchType.BINARYShawn O. Pearce, Dec 12, 2008
  9. 08/15 Always use the FileHeader buffer during Patch.parseHunksShawn O. Pearce, Dec 12, 2008
  10. 09/15 Parse "GIT binary patch" style patch metadataShawn O. Pearce, Dec 12, 2008
  11. 10/15 Record patch parsing errors for later inspection by applicationsShawn O. Pearce, Dec 12, 2008
  12. 11/15 Fix Patch.parse to honor the end point passed inShawn O. Pearce, Dec 12, 2008
  13. 12/15 Correctly handle hunk headers such as "@@ -0,0 +1 @@"Shawn O. Pearce, Dec 12, 2008
  14. 13/15 Patch parse test comparing "git log -p" output to "git log --numstat"Shawn O. Pearce, Dec 12, 2008
  15. 14/15 Abstract the hunk header testing into a methodShawn O. Pearce, Dec 12, 2008
  16. 15/15 Treat "diff --combined" the same as "diff --cc"Shawn O. Pearce, Dec 12, 2008
  17. Robin RosenbergDec 12, 2008
  18. 15/15 Treat "diff --combined" the same as "diff --cc"Shawn O. Pearce, Dec 12, 2008
  19. Shawn O. PearceDec 12, 2008
  20. Sverre RabbelierDec 12, 2008
  21. Shawn O. PearceDec 12, 2008
  22. Sverre RabbelierDec 12, 2008

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.