Commit 19e4b90712e9a185c4562e0563aa5a34dc6f549c

Stefan Sperling 2019-08-08T12:22:52

fix and test 'q' command for unstage -p

diff --git a/lib/worktree.c b/lib/worktree.c
index bd84650..070abf5 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -5321,12 +5321,23 @@ apply_or_reject_change(int *choice, struct got_diff_change *change, int n,
 		    end_old, start_new, end_new, rejectfile, outfile);
 		break;
 	case GOT_PATCH_CHOICE_QUIT:
-		/* Copy old file's lines until EOF. */
-		while (!feof(f1)) {
-			err = copy_one_line(f1, outfile, rejectfile);
-			if (err)
-				goto done;
-			(*line_cur1)++;
+		if (outfile) {
+			/* Copy old file's lines until EOF. */
+			while (!feof(f1)) {
+				err = copy_one_line(f1, outfile, NULL);
+				if (err)
+					goto done;
+				(*line_cur1)++;
+			}
+		}
+		if (rejectfile) {
+			/* Copy new file's lines until EOF. */
+			while (!feof(f2)) {
+				err = copy_one_line(f2, NULL, rejectfile);
+				if (err)
+					goto done;
+				(*line_cur2)++;
+			}
 		}
 		break;
 	default:
@@ -5731,7 +5742,7 @@ create_unstaged_content(char **path_unstaged_content,
 			goto done;
 		if (choice == GOT_PATCH_CHOICE_YES)
 			have_content = 1;
-		if (choice == GOT_PATCH_CHOICE_NO)
+		else
 			have_rejected_content = 1;
 		if (choice == GOT_PATCH_CHOICE_QUIT)
 			break;
diff --git a/regress/cmdline/unstage.sh b/regress/cmdline/unstage.sh
index aa8c840..07c730e 100755
--- a/regress/cmdline/unstage.sh
+++ b/regress/cmdline/unstage.sh
@@ -684,7 +684,158 @@ function test_unstage_patch_removed {
 	test_done "$testroot" "$ret"
 }
 
+function test_unstage_patch_quit {
+	local testroot=`test_init unstage_patch_quit`
+
+	jot 16 > $testroot/repo/numbers
+	echo zzz > $testroot/repo/zzz
+	(cd $testroot/repo && git add numbers zzz)
+	git_commit $testroot/repo -m "added files"
+	local commit_id=`git_show_head $testroot/repo`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	sed -i -e 's/^2$/a/' $testroot/wt/numbers
+	sed -i -e 's/^7$/b/' $testroot/wt/numbers
+	sed -i -e 's/^16$/c/' $testroot/wt/numbers
+	(cd $testroot/wt && got rm zzz > /dev/null)
+	(cd $testroot/wt && got stage > /dev/null)
+
+	# unstage first hunk and quit; and don't pass a path argument to
+	# ensure that we don't skip asking about the 'zzz' file after 'quit'
+	printf "y\nq\nn\n" > $testroot/patchscript
+	(cd $testroot/wt && got unstage -F $testroot/patchscript -p \
+		> $testroot/stdout)
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		echo "got stage command failed unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+	cat > $testroot/stdout.expected <<EOF
+-----------------------------------------------
+@@ -1,5 +1,5 @@
+ 1
+-2
++a
+ 3
+ 4
+ 5
+-----------------------------------------------
+M  numbers (change 1 of 3)
+unstage this change? [y/n/q] y
+-----------------------------------------------
+@@ -4,7 +4,7 @@
+ 4
+ 5
+ 6
+-7
++b
+ 8
+ 9
+ 10
+-----------------------------------------------
+M  numbers (change 2 of 3)
+unstage this change? [y/n/q] q
+G  numbers
+D  zzz
+unstage this deletion? [y/n] n
+EOF
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got status > $testroot/stdout)
+	echo "MM numbers" > $testroot/stdout.expected
+	echo " D zzz" >> $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got diff > $testroot/stdout)
+
+	echo "diff $commit_id $testroot/wt" > $testroot/stdout.expected
+	echo -n 'blob - ' >> $testroot/stdout.expected
+	(cd $testroot/wt && got stage -l numbers) | cut -d' ' -f 1 \
+		>> $testroot/stdout.expected
+	echo "file + numbers" >> $testroot/stdout.expected
+	echo "--- numbers" >> $testroot/stdout.expected
+	echo "+++ numbers" >> $testroot/stdout.expected
+	echo "@@ -1,5 +1,5 @@" >> $testroot/stdout.expected
+	echo " 1" >> $testroot/stdout.expected
+	echo "-2" >> $testroot/stdout.expected
+	echo "+a" >> $testroot/stdout.expected
+	echo " 3" >> $testroot/stdout.expected
+	echo " 4" >> $testroot/stdout.expected
+	echo " 5" >> $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got diff -s > $testroot/stdout)
+	echo "diff $commit_id $testroot/wt (staged changes)" \
+		> $testroot/stdout.expected
+	echo -n 'blob - ' >> $testroot/stdout.expected
+	got tree -r $testroot/repo -i -c $commit_id \
+		| grep 'numbers$' | cut -d' ' -f 1 \
+		>> $testroot/stdout.expected
+	echo -n 'blob + ' >> $testroot/stdout.expected
+	(cd $testroot/wt && got stage -l numbers) | cut -d' ' -f 1 \
+		>> $testroot/stdout.expected
+	cat >> $testroot/stdout.expected <<EOF
+--- numbers
++++ numbers
+@@ -4,7 +4,7 @@
+ 4
+ 5
+ 6
+-7
++b
+ 8
+ 9
+ 10
+@@ -13,4 +13,4 @@
+ 13
+ 14
+ 15
+-16
++c
+EOF
+	echo -n 'blob - ' >> $testroot/stdout.expected
+	got tree -r $testroot/repo -i | grep 'zzz$' | cut -d' ' -f 1 \
+		>> $testroot/stdout.expected
+	echo 'blob + /dev/null' >> $testroot/stdout.expected
+	echo "--- zzz" >> $testroot/stdout.expected
+	echo "+++ /dev/null" >> $testroot/stdout.expected
+	echo "@@ -1 +0,0 @@" >> $testroot/stdout.expected
+	echo "-zzz" >> $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+	fi
+	test_done "$testroot" "$ret"
+}
+
 run_test test_unstage_basic
 run_test test_unstage_patch
 run_test test_unstage_patch_added
 run_test test_unstage_patch_removed
+run_test test_unstage_patch_quit