| #!/bin/sh | 
 | # | 
 | # Copyright (c) 2011 David Caldwell | 
 | # | 
 |  | 
 | test_description='Test git stash --include-untracked' | 
 |  | 
 | . ./test-lib.sh | 
 |  | 
 | test_expect_success 'stash save --include-untracked some dirty working directory' ' | 
 | 	echo 1 >file && | 
 | 	git add file && | 
 | 	test_tick && | 
 | 	git commit -m initial && | 
 | 	echo 2 >file && | 
 | 	git add file && | 
 | 	echo 3 >file && | 
 | 	test_tick && | 
 | 	echo 1 >file2 && | 
 | 	echo 1 >HEAD && | 
 | 	mkdir untracked && | 
 | 	echo untracked >untracked/untracked && | 
 | 	git stash --include-untracked && | 
 | 	git diff-files --quiet && | 
 | 	git diff-index --cached --quiet HEAD | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --include-untracked cleaned the untracked files' ' | 
 | 	cat >expect <<-EOF && | 
 | 	?? actual | 
 | 	?? expect | 
 | 	EOF | 
 |  | 
 | 	git status --porcelain >actual && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --include-untracked stashed the untracked files' ' | 
 | 	one_blob=$(echo 1 | git hash-object --stdin) && | 
 | 	tracked=$(git rev-parse --short "$one_blob") && | 
 | 	untracked_blob=$(echo untracked | git hash-object --stdin) && | 
 | 	untracked=$(git rev-parse --short "$untracked_blob") && | 
 | 	cat >expect.diff <<-EOF && | 
 | 	diff --git a/HEAD b/HEAD | 
 | 	new file mode 100644 | 
 | 	index 0000000..$tracked | 
 | 	--- /dev/null | 
 | 	+++ b/HEAD | 
 | 	@@ -0,0 +1 @@ | 
 | 	+1 | 
 | 	diff --git a/file2 b/file2 | 
 | 	new file mode 100644 | 
 | 	index 0000000..$tracked | 
 | 	--- /dev/null | 
 | 	+++ b/file2 | 
 | 	@@ -0,0 +1 @@ | 
 | 	+1 | 
 | 	diff --git a/untracked/untracked b/untracked/untracked | 
 | 	new file mode 100644 | 
 | 	index 0000000..$untracked | 
 | 	--- /dev/null | 
 | 	+++ b/untracked/untracked | 
 | 	@@ -0,0 +1 @@ | 
 | 	+untracked | 
 | 	EOF | 
 | 	cat >expect.lstree <<-EOF && | 
 | 	HEAD | 
 | 	file2 | 
 | 	untracked | 
 | 	EOF | 
 |  | 
 | 	test_path_is_missing file2 && | 
 | 	test_path_is_missing untracked && | 
 | 	test_path_is_missing HEAD && | 
 | 	git diff HEAD stash^3 -- HEAD file2 untracked >actual && | 
 | 	test_cmp expect.diff actual && | 
 | 	git ls-tree --name-only stash^3: >actual && | 
 | 	test_cmp expect.lstree actual | 
 | ' | 
 | test_expect_success 'stash save --patch --include-untracked fails' ' | 
 | 	test_must_fail git stash --patch --include-untracked | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --patch --all fails' ' | 
 | 	test_must_fail git stash --patch --all | 
 | ' | 
 |  | 
 | test_expect_success 'clean up untracked/untracked file to prepare for next tests' ' | 
 | 	git clean --force --quiet | 
 |  | 
 | ' | 
 |  | 
 | test_expect_success 'stash pop after save --include-untracked leaves files untracked again' ' | 
 | 	cat >expect <<-EOF && | 
 | 	 M file | 
 | 	?? HEAD | 
 | 	?? actual | 
 | 	?? expect | 
 | 	?? file2 | 
 | 	?? untracked/ | 
 | 	EOF | 
 |  | 
 | 	git stash pop && | 
 | 	git status --porcelain >actual && | 
 | 	test_cmp expect actual && | 
 | 	echo 1 >expect_file2 && | 
 | 	test_cmp expect_file2 file2 && | 
 | 	echo untracked >untracked_expect && | 
 | 	test_cmp untracked_expect untracked/untracked | 
 | ' | 
 |  | 
 | test_expect_success 'clean up untracked/ directory to prepare for next tests' ' | 
 | 	git clean --force --quiet -d | 
 | ' | 
 |  | 
 | test_expect_success 'stash save -u dirty index' ' | 
 | 	echo 4 >file3 && | 
 | 	git add file3 && | 
 | 	test_tick && | 
 | 	git stash -u | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --include-untracked dirty index got stashed' ' | 
 | 	four_blob=$(echo 4 | git hash-object --stdin) && | 
 | 	blob=$(git rev-parse --short "$four_blob") && | 
 | 	cat >expect <<-EOF && | 
 | 	diff --git a/file3 b/file3 | 
 | 	new file mode 100644 | 
 | 	index 0000000..$blob | 
 | 	--- /dev/null | 
 | 	+++ b/file3 | 
 | 	@@ -0,0 +1 @@ | 
 | 	+4 | 
 | 	EOF | 
 |  | 
 | 	git stash pop --index && | 
 | 	test_when_finished "git reset" && | 
 | 	git diff --cached >actual && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | # Must direct output somewhere where it won't be considered an untracked file | 
 | test_expect_success 'stash save --include-untracked -q is quiet' ' | 
 | 	echo 1 >file5 && | 
 | 	git stash save --include-untracked --quiet >.git/stash-output.out 2>&1 && | 
 | 	test_line_count = 0 .git/stash-output.out && | 
 | 	rm -f .git/stash-output.out | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --include-untracked removed files' ' | 
 | 	rm -f file && | 
 | 	git stash save --include-untracked && | 
 | 	echo 1 >expect && | 
 | 	test_when_finished "rm -f expect" && | 
 | 	test_cmp expect file | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --include-untracked removed files got stashed' ' | 
 | 	git stash pop && | 
 | 	test_path_is_missing file | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --include-untracked respects .gitignore' ' | 
 | 	cat >.gitignore <<-EOF && | 
 | 	.gitignore | 
 | 	ignored | 
 | 	ignored.d/ | 
 | 	EOF | 
 |  | 
 | 	echo ignored >ignored && | 
 | 	mkdir ignored.d && | 
 | 	echo ignored >ignored.d/untracked && | 
 | 	git stash -u && | 
 | 	test_file_not_empty ignored && | 
 | 	test_file_not_empty ignored.d/untracked && | 
 | 	test_file_not_empty .gitignore | 
 | ' | 
 |  | 
 | test_expect_success 'stash save -u can stash with only untracked files different' ' | 
 | 	echo 4 >file4 && | 
 | 	git stash -u && | 
 | 	test_path_is_missing file4 | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --all does not respect .gitignore' ' | 
 | 	git stash -a && | 
 | 	test_path_is_missing ignored && | 
 | 	test_path_is_missing ignored.d && | 
 | 	test_path_is_missing .gitignore | 
 | ' | 
 |  | 
 | test_expect_success 'stash save --all is stash poppable' ' | 
 | 	git stash pop && | 
 | 	test_file_not_empty ignored && | 
 | 	test_file_not_empty ignored.d/untracked && | 
 | 	test_file_not_empty .gitignore | 
 | ' | 
 |  | 
 | test_expect_success 'stash push --include-untracked with pathspec' ' | 
 | 	>foo && | 
 | 	>bar && | 
 | 	git stash push --include-untracked -- foo && | 
 | 	test_path_is_file bar && | 
 | 	test_path_is_missing foo && | 
 | 	git stash pop && | 
 | 	test_path_is_file bar && | 
 | 	test_path_is_file foo | 
 | ' | 
 |  | 
 | test_expect_success 'stash push with $IFS character' ' | 
 | 	>"foo bar" && | 
 | 	>foo && | 
 | 	>bar && | 
 | 	git add foo* && | 
 | 	git stash push --include-untracked -- "foo b*" && | 
 | 	test_path_is_missing "foo bar" && | 
 | 	test_path_is_file foo && | 
 | 	test_path_is_file bar && | 
 | 	git stash pop && | 
 | 	test_path_is_file "foo bar" && | 
 | 	test_path_is_file foo && | 
 | 	test_path_is_file bar | 
 | ' | 
 |  | 
 | test_expect_success 'stash previously ignored file' ' | 
 | 	cat >.gitignore <<-EOF && | 
 | 	ignored | 
 | 	ignored.d/* | 
 | 	EOF | 
 |  | 
 | 	git reset HEAD && | 
 | 	git add .gitignore && | 
 | 	git commit -m "Add .gitignore" && | 
 | 	>ignored.d/foo && | 
 | 	echo "!ignored.d/foo" >>.gitignore && | 
 | 	git stash save --include-untracked && | 
 | 	test_path_is_missing ignored.d/foo && | 
 | 	git stash pop && | 
 | 	test_path_is_file ignored.d/foo | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u -- <untracked> doesnt print error' ' | 
 | 	>untracked && | 
 | 	git stash push -u -- untracked 2>actual && | 
 | 	test_path_is_missing untracked && | 
 | 	test_line_count = 0 actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u -- <untracked> leaves rest of working tree in place' ' | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	>untracked && | 
 | 	git stash push -u -- untracked && | 
 | 	test_path_is_missing untracked && | 
 | 	test_path_is_file tracked | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u -- <tracked> <untracked> clears changes in both' ' | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	>untracked && | 
 | 	git stash push -u -- tracked untracked && | 
 | 	test_path_is_missing tracked && | 
 | 	test_path_is_missing untracked | 
 | ' | 
 |  | 
 | test_expect_success 'stash --all -- <ignored> stashes ignored file' ' | 
 | 	>ignored.d/bar && | 
 | 	git stash push --all -- ignored.d/bar && | 
 | 	test_path_is_missing ignored.d/bar | 
 | ' | 
 |  | 
 | test_expect_success 'stash --all -- <tracked> <ignored> clears changes in both' ' | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	>ignored.d/bar && | 
 | 	git stash push --all -- tracked ignored.d/bar && | 
 | 	test_path_is_missing tracked && | 
 | 	test_path_is_missing ignored.d/bar | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u -- <ignored> leaves ignored file alone' ' | 
 | 	>ignored.d/bar && | 
 | 	git stash push -u -- ignored.d/bar && | 
 | 	test_path_is_file ignored.d/bar | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u -- <non-existent> shows no changes when there are none' ' | 
 | 	git stash push -u -- non-existent >actual && | 
 | 	echo "No local changes to save" >expect && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u with globs' ' | 
 | 	>untracked.txt && | 
 | 	git stash -u -- ":(glob)**/*.txt" && | 
 | 	test_path_is_missing untracked.txt | 
 | ' | 
 |  | 
 | test_expect_success 'stash show --include-untracked shows untracked files' ' | 
 | 	git reset --hard && | 
 | 	git clean -xf && | 
 | 	>untracked && | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	empty_blob_oid=$(git rev-parse --short :tracked) && | 
 | 	git stash -u && | 
 |  | 
 | 	cat >expect <<-EOF && | 
 | 	 tracked   | 0 | 
 | 	 untracked | 0 | 
 | 	 2 files changed, 0 insertions(+), 0 deletions(-) | 
 | 	EOF | 
 | 	git stash show --include-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show -u >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --no-include-untracked --include-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --only-untracked --include-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git -c stash.showIncludeUntracked=true stash show >actual && | 
 | 	test_cmp expect actual && | 
 |  | 
 | 	cat >expect <<-EOF && | 
 | 	diff --git a/tracked b/tracked | 
 | 	new file mode 100644 | 
 | 	index 0000000..$empty_blob_oid | 
 | 	diff --git a/untracked b/untracked | 
 | 	new file mode 100644 | 
 | 	index 0000000..$empty_blob_oid | 
 | 	EOF | 
 | 	git stash show -p --include-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --include-untracked -p >actual && | 
 | 	test_cmp expect actual && | 
 | 	git -c stash.showIncludeUntracked=true stash show -p >actual && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash show --only-untracked only shows untracked files' ' | 
 | 	git reset --hard && | 
 | 	git clean -xf && | 
 | 	>untracked && | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	empty_blob_oid=$(git rev-parse --short :tracked) && | 
 | 	git stash -u && | 
 |  | 
 | 	cat >expect <<-EOF && | 
 | 	 untracked | 0 | 
 | 	 1 file changed, 0 insertions(+), 0 deletions(-) | 
 | 	EOF | 
 | 	git stash show --only-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --no-include-untracked --only-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --include-untracked --only-untracked >actual && | 
 | 	test_cmp expect actual && | 
 |  | 
 | 	cat >expect <<-EOF && | 
 | 	diff --git a/untracked b/untracked | 
 | 	new file mode 100644 | 
 | 	index 0000000..$empty_blob_oid | 
 | 	EOF | 
 | 	git stash show -p --only-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --only-untracked -p >actual && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash show --no-include-untracked cancels --{include,only}-untracked' ' | 
 | 	git reset --hard && | 
 | 	git clean -xf && | 
 | 	>untracked && | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	git stash -u && | 
 |  | 
 | 	cat >expect <<-EOF && | 
 | 	 tracked | 0 | 
 | 	 1 file changed, 0 insertions(+), 0 deletions(-) | 
 | 	EOF | 
 | 	git stash show --only-untracked --no-include-untracked >actual && | 
 | 	test_cmp expect actual && | 
 | 	git stash show --include-untracked --no-include-untracked >actual && | 
 | 	test_cmp expect actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash show --include-untracked errors on duplicate files' ' | 
 | 	git reset --hard && | 
 | 	git clean -xf && | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	tree=$(git write-tree) && | 
 | 	i_commit=$(git commit-tree -p HEAD -m "index on any-branch" "$tree") && | 
 | 	test_when_finished "rm -f untracked_index" && | 
 | 	u_commit=$( | 
 | 		GIT_INDEX_FILE="untracked_index" && | 
 | 		export GIT_INDEX_FILE && | 
 | 		git update-index --add tracked && | 
 | 		u_tree=$(git write-tree) && | 
 | 		git commit-tree -m "untracked files on any-branch" "$u_tree" | 
 | 	) && | 
 | 	w_commit=$(git commit-tree -p HEAD -p "$i_commit" -p "$u_commit" -m "WIP on any-branch" "$tree") && | 
 | 	test_must_fail git stash show --include-untracked "$w_commit" 2>err && | 
 | 	test_i18ngrep "worktree and untracked commit have duplicate entries: tracked" err | 
 | ' | 
 |  | 
 | test_expect_success 'stash show --{include,only}-untracked on stashes without untracked entries' ' | 
 | 	git reset --hard && | 
 | 	git clean -xf && | 
 | 	>tracked && | 
 | 	git add tracked && | 
 | 	git stash && | 
 |  | 
 | 	git stash show >expect && | 
 | 	git stash show --include-untracked >actual && | 
 | 	test_cmp expect actual && | 
 |  | 
 | 	git stash show --only-untracked >actual && | 
 | 	test_must_be_empty actual | 
 | ' | 
 |  | 
 | test_expect_success 'stash -u ignores sub-repository' ' | 
 | 	test_when_finished "rm -rf sub-repo" && | 
 | 	git init sub-repo && | 
 | 	git stash -u | 
 | ' | 
 |  | 
 | test_done |