Commit 54d5be07768d1e312078b5eb60f0e32738a1631a

Stefan Sperling 2021-06-03T13:12:58

fix unrelated changes being merged by got cherrypick/backout/rebase/histedit This was a long-standing and very annoying bug. The two xfail tests in the cherrypick test suite are passing now.

diff --git a/lib/worktree.c b/lib/worktree.c
index 555aa43..13cc9fb 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -767,7 +767,7 @@ static const struct got_error *
 merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
     FILE *f_orig, FILE *f_deriv, FILE *f_deriv2, const char *ondisk_path,
     const char *path, uint16_t st_mode,
-    const char *label_orig, const char *label_deriv,
+    const char *label_orig, const char *label_deriv, const char *label_deriv2,
     struct got_repository *repo,
     got_worktree_checkout_cb progress_cb, void *progress_arg)
 {
@@ -794,7 +794,7 @@ merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
 		goto done;
 
 	err = got_merge_diff3(&overlapcnt, merged_fd, f_deriv, f_orig,
-	    f_deriv2, label_deriv, label_orig, NULL);
+	    f_deriv2, label_deriv, label_orig, label_deriv2);
 	if (err)
 		goto done;
 
@@ -1179,7 +1179,7 @@ merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
 
 	err = merge_file(local_changes_subsumed, worktree, f_orig, f_deriv,
 	    f_deriv2, ondisk_path, path, st_mode, label_orig, label_deriv,
-	    repo, progress_cb, progress_arg);
+	    NULL, repo, progress_cb, progress_arg);
 done:
 	if (f_orig && fclose(f_orig) == EOF && err == NULL)
 		err = got_error_from_errno("fclose");
@@ -2834,7 +2834,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
 	unsigned char status;
 	int local_changes_subsumed;
 	FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
-	char *id_str = NULL, *label_deriv = NULL;
+	char *id_str = NULL, *label_deriv2 = NULL;
 
 	if (blob1 && blob2) {
 		ie = got_fileindex_entry_get(a->fileindex, path2,
@@ -2887,11 +2887,11 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
 			if (err)
 				goto done;
 
-			f_deriv = got_opentemp();
-			if (f_deriv == NULL)
+			f_deriv2 = got_opentemp();
+			if (f_deriv2 == NULL)
 				goto done;
 			err = got_object_blob_dump_to_file(NULL, NULL, NULL,
-			    f_deriv, blob2);
+			    f_deriv2, blob2);
 			if (err)
 				goto done;
 
@@ -2901,8 +2901,8 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
 				    ondisk_path);
 				goto done;
 			}
-			f_deriv2 = fdopen(fd, "r");
-			if (f_deriv2 == NULL) {
+			f_deriv = fdopen(fd, "r");
+			if (f_deriv == NULL) {
 				err = got_error_from_errno2("fdopen",
 				    ondisk_path);
 				close(fd);
@@ -2911,15 +2911,15 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
 			err = got_object_id_str(&id_str, a->commit_id2);
 			if (err)
 				goto done;
-			if (asprintf(&label_deriv, "%s: commit %s",
+			if (asprintf(&label_deriv2, "%s: commit %s",
 			    GOT_MERGE_LABEL_MERGED, id_str) == -1) {
 				err = got_error_from_errno("asprintf");
 				goto done;
 			}
 			err = merge_file(&local_changes_subsumed, a->worktree,
 			    f_orig, f_deriv, f_deriv2, ondisk_path, path2,
-			    sb.st_mode, a->label_orig, label_deriv, repo,
-			    a->progress_cb, a->progress_arg);
+			    sb.st_mode, a->label_orig, NULL, label_deriv2,
+			    repo, a->progress_cb, a->progress_arg);
 		}
 	} else if (blob1) {
 		ie = got_fileindex_entry_get(a->fileindex, path1,
@@ -3097,7 +3097,7 @@ done:
 	if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
 		err = got_error_from_errno("fclose");
 	free(id_str);
-	free(label_deriv);
+	free(label_deriv2);
 	free(ondisk_path);
 	return err;
 }
@@ -7872,7 +7872,7 @@ unstage_hunks(struct got_object_id *staged_blob_id,
 		err = merge_file(&local_changes_subsumed, worktree,
 		    f_base, f, f_deriv2, ondisk_path, ie->path,
 		    got_fileindex_perms_to_st(ie),
-		    label_orig, "unstaged",
+		    label_orig, "unstaged", NULL,
 		    repo, progress_cb, progress_arg);
 	}
 	if (err)
diff --git a/regress/cmdline/cherrypick.sh b/regress/cmdline/cherrypick.sh
index 516a404..5bfd952 100755
--- a/regress/cmdline/cherrypick.sh
+++ b/regress/cmdline/cherrypick.sh
@@ -855,8 +855,7 @@ test_cherrypick_conflict_no_eol2() {
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret="$?"
 	if [ "$ret" != "0" ]; then
-		#diff -u $testroot/stdout.expected $testroot/stdout
-		ret="xfail $(head -n 1 $testroot/stderr)"
+		diff -u $testroot/stdout.expected $testroot/stdout
 	fi
 	test_done "$testroot" "$ret"
 }
@@ -1189,8 +1188,7 @@ EOF
 	cmp -s $testroot/diff.expected $testroot/diff
 	ret="$?"
 	if [ "$ret" != "0" ]; then
-		#diff -u $testroot/diff.expected $testroot/diff
-		ret="xfail cherrypick results in unexpected diff"
+		diff -u $testroot/diff.expected $testroot/diff
 	fi
 
 	test_done "$testroot" "$ret"
diff --git a/regress/cmdline/rebase.sh b/regress/cmdline/rebase.sh
index 432e94f..a1f81c4 100755
--- a/regress/cmdline/rebase.sh
+++ b/regress/cmdline/rebase.sh
@@ -279,15 +279,15 @@ test_rebase_continue() {
 		return 1
 	fi
 
-	echo "<<<<<<< merged change: commit $orig_commit1" \
-		> $testroot/content.expected
-	echo "modified alpha on branch" >> $testroot/content.expected
+	echo '<<<<<<<' > $testroot/content.expected
+	echo "modified alpha on master" >> $testroot/content.expected
 	echo "||||||| 3-way merge base: commit $init_commit" \
 		>> $testroot/content.expected
 	echo "alpha" >> $testroot/content.expected
 	echo "=======" >> $testroot/content.expected
-	echo "modified alpha on master" >> $testroot/content.expected
-	echo '>>>>>>>' >> $testroot/content.expected
+	echo "modified alpha on branch" >> $testroot/content.expected
+	echo ">>>>>>> merged change: commit $orig_commit1" \
+		>> $testroot/content.expected
 	cat $testroot/wt/alpha > $testroot/content
 	cmp -s $testroot/content.expected $testroot/content
 	ret="$?"
@@ -415,15 +415,15 @@ test_rebase_abort() {
 		return 1
 	fi
 
-	echo "<<<<<<< merged change: commit $orig_commit1" \
-		> $testroot/content.expected
-	echo "modified alpha on branch" >> $testroot/content.expected
+	echo '<<<<<<<' > $testroot/content.expected
+	echo "modified alpha on master" >> $testroot/content.expected
 	echo "||||||| 3-way merge base: commit $init_commit" \
 		>> $testroot/content.expected
 	echo "alpha" >> $testroot/content.expected
 	echo "=======" >> $testroot/content.expected
-	echo "modified alpha on master" >> $testroot/content.expected
-	echo '>>>>>>>' >> $testroot/content.expected
+	echo "modified alpha on branch" >> $testroot/content.expected
+	echo ">>>>>>> merged change: commit $orig_commit1" \
+		>> $testroot/content.expected
 	cat $testroot/wt/alpha > $testroot/content
 	cmp -s $testroot/content.expected $testroot/content
 	ret="$?"
@@ -532,15 +532,15 @@ test_rebase_no_op_change() {
 		return 1
 	fi
 
-	echo "<<<<<<< merged change: commit $orig_commit1" \
-		> $testroot/content.expected
-	echo "modified alpha on branch" >> $testroot/content.expected
+	echo '<<<<<<<' > $testroot/content.expected
+	echo "modified alpha on master" >> $testroot/content.expected
 	echo "||||||| 3-way merge base: commit $init_commit" \
 		>> $testroot/content.expected
 	echo "alpha" >> $testroot/content.expected
 	echo "=======" >> $testroot/content.expected
-	echo "modified alpha on master" >> $testroot/content.expected
-	echo '>>>>>>>' >> $testroot/content.expected
+	echo "modified alpha on branch" >> $testroot/content.expected
+	echo ">>>>>>> merged change: commit $orig_commit1" \
+		>> $testroot/content.expected
 	cat $testroot/wt/alpha > $testroot/content
 	cmp -s $testroot/content.expected $testroot/content
 	ret="$?"
@@ -644,15 +644,15 @@ test_rebase_in_progress() {
 		return 1
 	fi
 
-	echo "<<<<<<< merged change: commit $orig_commit1" \
-		> $testroot/content.expected
-	echo "modified alpha on branch" >> $testroot/content.expected
+	echo '<<<<<<<' > $testroot/content.expected
+	echo "modified alpha on master" >> $testroot/content.expected
 	echo "||||||| 3-way merge base: commit $init_commit" \
 		>> $testroot/content.expected
 	echo "alpha" >> $testroot/content.expected
 	echo "=======" >> $testroot/content.expected
-	echo "modified alpha on master" >> $testroot/content.expected
-	echo '>>>>>>>' >> $testroot/content.expected
+	echo "modified alpha on branch" >> $testroot/content.expected
+	echo ">>>>>>> merged change: commit $orig_commit1" \
+		>> $testroot/content.expected
 	cat $testroot/wt/alpha > $testroot/content
 	cmp -s $testroot/content.expected $testroot/content
 	ret="$?"