Commit d8b5af438b16bcea5568b1d4bfc127567e35e2f6

Omar Polo 2022-06-19T11:51:33

use the commitid in the patch diff3 conflict header suggested by and ok stsp@

diff --git a/lib/got_lib_privsep.h b/lib/got_lib_privsep.h
index 8b9f4c0..8e99bbe 100644
--- a/lib/got_lib_privsep.h
+++ b/lib/got_lib_privsep.h
@@ -613,6 +613,7 @@ struct got_imsg_patch {
 	int	git;
 	char	old[PATH_MAX];
 	char	new[PATH_MAX];
+	char	cid[41];
 	char	blob[41];
 };
 
diff --git a/lib/patch.c b/lib/patch.c
index 9fbe217..9209e54 100644
--- a/lib/patch.c
+++ b/lib/patch.c
@@ -73,6 +73,7 @@ STAILQ_HEAD(got_patch_hunk_head, got_patch_hunk);
 struct got_patch {
 	char	*old;
 	char	*new;
+	char	 cid[41];
 	char	 blob[41];
 	struct got_patch_hunk_head head;
 };
@@ -185,12 +186,16 @@ recv_patch(struct imsgbuf *ibuf, int *done, struct got_patch *p, int strip)
 
 	if (patch.old[sizeof(patch.old)-1] != '\0' ||
 	    patch.new[sizeof(patch.new)-1] != '\0' ||
+	    patch.cid[sizeof(patch.cid)-1] != '\0' ||
 	    patch.blob[sizeof(patch.blob)-1] != '\0') {
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
 		goto done;
 	}
 
-	strlcpy(p->blob, patch.blob, sizeof(p->blob));
+	if (*patch.cid != '\0' && *patch.blob != '\0') {
+		strlcpy(p->cid, patch.cid, sizeof(p->cid));
+		strlcpy(p->blob, patch.blob, sizeof(p->blob));
+	}
 
 	/* automatically set strip=1 for git-style diffs */
 	if (strip == -1 && patch.git &&
@@ -624,7 +629,7 @@ apply_patch(int *overlapcnt, struct got_worktree *worktree,
 {
 	const struct got_error *err = NULL;
 	int do_merge = 0, file_renamed = 0;
-	char *oldlabel = NULL, *newlabel = NULL;
+	char *oldlabel = NULL, *newlabel = NULL, *anclabel = NULL;
 	char *oldpath = NULL, *newpath = NULL;
 	char *tmppath = NULL, *template = NULL, *parent = NULL;
 	char *apath = NULL, *mergepath = NULL;
@@ -699,6 +704,12 @@ apply_patch(int *overlapcnt, struct got_worktree *worktree,
 			goto done;
 		}
 
+		if (asprintf(&anclabel, "commit %s", p->cid) == -1) {
+			err = got_error_from_errno("asprintf");
+			anclabel = NULL;
+			goto done;
+		}
+
 		err = got_opentemp_named(&mergepath, &mergefile, template);
 		if (err)
 			goto done;
@@ -706,7 +717,7 @@ apply_patch(int *overlapcnt, struct got_worktree *worktree,
 		outfd = fileno(mergefile);
 
 		err = got_merge_diff3(overlapcnt, outfd, tmpfile, afile,
-		    oldfile, oldlabel, p->blob, newlabel,
+		    oldfile, oldlabel, anclabel, newlabel,
 		    GOT_DIFF_ALGORITHM_PATIENCE);
 		if (err)
 			goto done;
@@ -794,6 +805,7 @@ done:
 	free(newpath);
 	free(oldlabel);
 	free(newlabel);
+	free(anclabel);
 	return err;
 }
 
diff --git a/libexec/got-read-patch/got-read-patch.c b/libexec/got-read-patch/got-read-patch.c
index ba9f841..5f1a284 100644
--- a/libexec/got-read-patch/got-read-patch.c
+++ b/libexec/got-read-patch/got-read-patch.c
@@ -61,7 +61,8 @@
 struct imsgbuf ibuf;
 
 static const struct got_error *
-send_patch(const char *oldname, const char *newname, const char *blob, int git)
+send_patch(const char *oldname, const char *newname, const char *commitid,
+    const char *blob, int git)
 {
 	struct got_imsg_patch p;
 
@@ -73,8 +74,10 @@ send_patch(const char *oldname, const char *newname, const char *blob, int git)
 	if (newname != NULL)
 		strlcpy(p.new, newname, sizeof(p.new));
 
-	if (blob != NULL)
+	if (commitid != NULL && blob != NULL) {
+		strlcpy(p.cid, commitid, sizeof(p.cid));
 		strlcpy(p.blob, blob, sizeof(p.blob));
+	}
 
 	p.git = git;
 	if (imsg_compose(&ibuf, GOT_IMSG_PATCH, 0, 0, -1, &p, sizeof(p)) == -1)
@@ -150,7 +153,7 @@ find_patch(int *done, FILE *fp)
 {
 	const struct got_error *err = NULL;
 	char	*old = NULL, *new = NULL;
-	char	*blob = NULL;
+	char	*commitid = NULL, *blob = NULL;
 	char	*line = NULL;
 	size_t	 linesize = 0;
 	ssize_t	 linelen;
@@ -181,8 +184,13 @@ find_patch(int *done, FILE *fp)
 			rename = 1;
 		else if (!strncmp(line, "diff --git a/", 13)) {
 			git = 1;
+			free(commitid);
+			commitid = NULL;
 			free(blob);
 			blob = NULL;
+		} else if (!git && !strncmp(line, "diff ", 5)) {
+			free(commitid);
+			err = blobid(line + 5, &commitid);
 		}
 
 		if (err)
@@ -195,7 +203,8 @@ find_patch(int *done, FILE *fp)
 		 */
 		if (rename && old != NULL && new != NULL) {
 			*done = 1;
-			err = send_patch(old, new, blob, git);
+			err = send_patch(old, new, commitid,
+			    blob, git);
 			break;
 		}
 
@@ -205,7 +214,8 @@ find_patch(int *done, FILE *fp)
 			    (!create && old == NULL))
 				err = got_error(GOT_ERR_PATCH_MALFORMED);
 			else
-				err = send_patch(old, new, blob, git);
+				err = send_patch(old, new, commitid,
+				    blob, git);
 
 			if (err)
 				break;
@@ -219,6 +229,7 @@ find_patch(int *done, FILE *fp)
 
 	free(old);
 	free(new);
+	free(commitid);
 	free(blob);
 	free(line);
 	if (ferror(fp) && err == NULL)
diff --git a/regress/cmdline/patch.sh b/regress/cmdline/patch.sh
index 6c9ee03..20e899e 100755
--- a/regress/cmdline/patch.sh
+++ b/regress/cmdline/patch.sh
@@ -1517,6 +1517,8 @@ test_patch_merge_conflict() {
 		return 1
 	fi
 
+	local commit_id=`git_show_head $testroot/repo`
+
 	jot 10 | sed 's/6/six/g' > $testroot/wt/numbers
 
 	(cd $testroot/wt && got diff > $testroot/old.diff \
@@ -1555,7 +1557,7 @@ test_patch_merge_conflict() {
 	5
 	<<<<<<< --- numbers
 	six
-	||||||| f00c965d8307308469e537302baa73048488f162
+	||||||| commit $commit_id
 	6
 	=======
 	3+3