diff mbox series

[v2,1/3] t7012: add a testcase demonstrating stash apply bugs in sparse checkouts

Message ID 2155bbfe205588387208690abf8071d462c69d64.1606861519.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Fix stash apply in sparse checkouts (and a submodule test) | expand

Commit Message

Elijah Newren Dec. 1, 2020, 10:25 p.m. UTC
From: Elijah Newren <newren@gmail.com>

Applying stashes in sparse-checkouts, particularly when the patterns
used to define the sparseness have changed between when the stash was
created and when it is applied, has a number of bugs.  The primary
problem is that stashes are sometimes only partially applied.  In most
such cases, it does so silently without any warning or error being
displayed and with 0 exit status.

There are, however, a few cases when non-translated error messages are
shown and the stash application aborts early.  The first is when there
are files present despite the SKIP_WORKTREE bit being set, in which case
the error message shown is:

    error: Entry 'PATHNAME' not uptodate. Cannot merge.

The other situation is when a stash contains new files to add to the
working tree; in this case, the code aborts early but still has the
stash partially applied, and shows the following error message:

    error: NEWFILE: does not exist and --remove not passed
    fatal: Unable to process path NEWFILE

Add a test that can trigger all three of these problems.  Have it
carefully check that the working copy and SKIP_WORKTREE bits are as
expected after the stash application.  The test is currently marked as
expected to fail, but subsequent commits will implement the fixes and
toggle the expectation.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 t/t7012-skip-worktree-writing.sh | 88 ++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
diff mbox series

Patch

diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh
index 7476781979..a184ee97fb 100755
--- a/t/t7012-skip-worktree-writing.sh
+++ b/t/t7012-skip-worktree-writing.sh
@@ -149,6 +149,94 @@  test_expect_success '--ignore-skip-worktree-entries leaves worktree alone' '
 		--diff-filter=D -- keep-me.t
 '
 
+test_expect_failure 'stash restore in sparse checkout' '
+	test_create_repo stash-restore &&
+	(
+		cd stash-restore &&
+
+		mkdir subdir &&
+		echo A >subdir/A &&
+		echo untouched >untouched &&
+		echo removeme >removeme &&
+		echo modified >modified &&
+		git add . &&
+		git commit -m Initial &&
+
+		echo AA >>subdir/A &&
+		echo addme >addme &&
+		echo tweaked >>modified &&
+		rm removeme &&
+		git add addme &&
+
+		git stash push &&
+
+		git sparse-checkout set subdir &&
+
+		# Ensure after sparse-checkout we only have expected files
+		cat >expect <<-EOF &&
+		S modified
+		S removeme
+		H subdir/A
+		S untouched
+		EOF
+		git ls-files -t >actual &&
+		test_cmp expect actual &&
+
+		test_path_is_missing addme &&
+		test_path_is_missing modified &&
+		test_path_is_missing removeme &&
+		test_path_is_file    subdir/A &&
+		test_path_is_missing untouched &&
+
+		# Put a file in the working directory in the way
+		echo in the way >modified &&
+		git stash apply &&
+
+		# Ensure stash vivifies modifies paths...
+		cat >expect <<-EOF &&
+		H addme
+		H modified
+		H removeme
+		H subdir/A
+		S untouched
+		EOF
+		git ls-files -t >actual &&
+		test_cmp expect actual &&
+
+		# ...and that the paths show up in status as changed...
+		cat >expect <<-EOF &&
+		A  addme
+		 M modified
+		 D removeme
+		 M subdir/A
+		?? actual
+		?? expect
+		?? modified.stash.XXXXXX
+		EOF
+		git status --porcelain | \
+			sed -e s/stash......./stash.XXXXXX/ >actual &&
+		test_cmp expect actual &&
+
+		# ...and that working directory reflects the files correctly
+		test_path_is_file    addme &&
+		test_path_is_file    modified &&
+		test_path_is_missing removeme &&
+		test_path_is_file    subdir/A &&
+		test_path_is_missing untouched &&
+
+		# ...including that we have the expected "modified" file...
+		cat >expect <<-EOF &&
+		modified
+		tweaked
+		EOF
+		test_cmp expect modified &&
+
+		# ...and that the other "modified" file is still present...
+		echo in the way >expect &&
+		test_cmp expect modified.stash.*
+	)
+'
+
 #TODO test_expect_failure 'git-apply adds file' false
 #TODO test_expect_failure 'git-apply updates file' false
 #TODO test_expect_failure 'git-apply removes file' false