stash show: teach --include-untracked and --only-untracked
[git] / t / t3905-stash-include-untracked.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2011 David Caldwell
4 #
5
6 test_description='Test git stash --include-untracked'
7
8 . ./test-lib.sh
9
10 test_expect_success 'stash save --include-untracked some dirty working directory' '
11         echo 1 >file &&
12         git add file &&
13         test_tick &&
14         git commit -m initial &&
15         echo 2 >file &&
16         git add file &&
17         echo 3 >file &&
18         test_tick &&
19         echo 1 >file2 &&
20         echo 1 >HEAD &&
21         mkdir untracked &&
22         echo untracked >untracked/untracked &&
23         git stash --include-untracked &&
24         git diff-files --quiet &&
25         git diff-index --cached --quiet HEAD
26 '
27
28 test_expect_success 'stash save --include-untracked cleaned the untracked files' '
29         cat >expect <<-EOF &&
30         ?? actual
31         ?? expect
32         EOF
33
34         git status --porcelain >actual &&
35         test_cmp expect actual
36 '
37
38 test_expect_success 'stash save --include-untracked stashed the untracked files' '
39         one_blob=$(echo 1 | git hash-object --stdin) &&
40         tracked=$(git rev-parse --short "$one_blob") &&
41         untracked_blob=$(echo untracked | git hash-object --stdin) &&
42         untracked=$(git rev-parse --short "$untracked_blob") &&
43         cat >expect.diff <<-EOF &&
44         diff --git a/HEAD b/HEAD
45         new file mode 100644
46         index 0000000..$tracked
47         --- /dev/null
48         +++ b/HEAD
49         @@ -0,0 +1 @@
50         +1
51         diff --git a/file2 b/file2
52         new file mode 100644
53         index 0000000..$tracked
54         --- /dev/null
55         +++ b/file2
56         @@ -0,0 +1 @@
57         +1
58         diff --git a/untracked/untracked b/untracked/untracked
59         new file mode 100644
60         index 0000000..$untracked
61         --- /dev/null
62         +++ b/untracked/untracked
63         @@ -0,0 +1 @@
64         +untracked
65         EOF
66         cat >expect.lstree <<-EOF &&
67         HEAD
68         file2
69         untracked
70         EOF
71
72         test_path_is_missing file2 &&
73         test_path_is_missing untracked &&
74         test_path_is_missing HEAD &&
75         git diff HEAD stash^3 -- HEAD file2 untracked >actual &&
76         test_cmp expect.diff actual &&
77         git ls-tree --name-only stash^3: >actual &&
78         test_cmp expect.lstree actual
79 '
80 test_expect_success 'stash save --patch --include-untracked fails' '
81         test_must_fail git stash --patch --include-untracked
82 '
83
84 test_expect_success 'stash save --patch --all fails' '
85         test_must_fail git stash --patch --all
86 '
87
88 test_expect_success 'clean up untracked/untracked file to prepare for next tests' '
89         git clean --force --quiet
90
91 '
92
93 test_expect_success 'stash pop after save --include-untracked leaves files untracked again' '
94         cat >expect <<-EOF &&
95          M file
96         ?? HEAD
97         ?? actual
98         ?? expect
99         ?? file2
100         ?? untracked/
101         EOF
102
103         git stash pop &&
104         git status --porcelain >actual &&
105         test_cmp expect actual &&
106         echo 1 >expect_file2 &&
107         test_cmp expect_file2 file2 &&
108         echo untracked >untracked_expect &&
109         test_cmp untracked_expect untracked/untracked
110 '
111
112 test_expect_success 'clean up untracked/ directory to prepare for next tests' '
113         git clean --force --quiet -d
114 '
115
116 test_expect_success 'stash save -u dirty index' '
117         echo 4 >file3 &&
118         git add file3 &&
119         test_tick &&
120         git stash -u
121 '
122
123 test_expect_success 'stash save --include-untracked dirty index got stashed' '
124         four_blob=$(echo 4 | git hash-object --stdin) &&
125         blob=$(git rev-parse --short "$four_blob") &&
126         cat >expect <<-EOF &&
127         diff --git a/file3 b/file3
128         new file mode 100644
129         index 0000000..$blob
130         --- /dev/null
131         +++ b/file3
132         @@ -0,0 +1 @@
133         +4
134         EOF
135
136         git stash pop --index &&
137         test_when_finished "git reset" &&
138         git diff --cached >actual &&
139         test_cmp expect actual
140 '
141
142 # Must direct output somewhere where it won't be considered an untracked file
143 test_expect_success 'stash save --include-untracked -q is quiet' '
144         echo 1 >file5 &&
145         git stash save --include-untracked --quiet >.git/stash-output.out 2>&1 &&
146         test_line_count = 0 .git/stash-output.out &&
147         rm -f .git/stash-output.out
148 '
149
150 test_expect_success 'stash save --include-untracked removed files' '
151         rm -f file &&
152         git stash save --include-untracked &&
153         echo 1 >expect &&
154         test_when_finished "rm -f expect" &&
155         test_cmp expect file
156 '
157
158 test_expect_success 'stash save --include-untracked removed files got stashed' '
159         git stash pop &&
160         test_path_is_missing file
161 '
162
163 test_expect_success 'stash save --include-untracked respects .gitignore' '
164         cat >.gitignore <<-EOF &&
165         .gitignore
166         ignored
167         ignored.d/
168         EOF
169
170         echo ignored >ignored &&
171         mkdir ignored.d &&
172         echo ignored >ignored.d/untracked &&
173         git stash -u &&
174         test_file_not_empty ignored &&
175         test_file_not_empty ignored.d/untracked &&
176         test_file_not_empty .gitignore
177 '
178
179 test_expect_success 'stash save -u can stash with only untracked files different' '
180         echo 4 >file4 &&
181         git stash -u &&
182         test_path_is_missing file4
183 '
184
185 test_expect_success 'stash save --all does not respect .gitignore' '
186         git stash -a &&
187         test_path_is_missing ignored &&
188         test_path_is_missing ignored.d &&
189         test_path_is_missing .gitignore
190 '
191
192 test_expect_success 'stash save --all is stash poppable' '
193         git stash pop &&
194         test_file_not_empty ignored &&
195         test_file_not_empty ignored.d/untracked &&
196         test_file_not_empty .gitignore
197 '
198
199 test_expect_success 'stash push --include-untracked with pathspec' '
200         >foo &&
201         >bar &&
202         git stash push --include-untracked -- foo &&
203         test_path_is_file bar &&
204         test_path_is_missing foo &&
205         git stash pop &&
206         test_path_is_file bar &&
207         test_path_is_file foo
208 '
209
210 test_expect_success 'stash push with $IFS character' '
211         >"foo bar" &&
212         >foo &&
213         >bar &&
214         git add foo* &&
215         git stash push --include-untracked -- "foo b*" &&
216         test_path_is_missing "foo bar" &&
217         test_path_is_file foo &&
218         test_path_is_file bar &&
219         git stash pop &&
220         test_path_is_file "foo bar" &&
221         test_path_is_file foo &&
222         test_path_is_file bar
223 '
224
225 test_expect_success 'stash previously ignored file' '
226         cat >.gitignore <<-EOF &&
227         ignored
228         ignored.d/*
229         EOF
230
231         git reset HEAD &&
232         git add .gitignore &&
233         git commit -m "Add .gitignore" &&
234         >ignored.d/foo &&
235         echo "!ignored.d/foo" >>.gitignore &&
236         git stash save --include-untracked &&
237         test_path_is_missing ignored.d/foo &&
238         git stash pop &&
239         test_path_is_file ignored.d/foo
240 '
241
242 test_expect_success 'stash -u -- <untracked> doesnt print error' '
243         >untracked &&
244         git stash push -u -- untracked 2>actual &&
245         test_path_is_missing untracked &&
246         test_line_count = 0 actual
247 '
248
249 test_expect_success 'stash -u -- <untracked> leaves rest of working tree in place' '
250         >tracked &&
251         git add tracked &&
252         >untracked &&
253         git stash push -u -- untracked &&
254         test_path_is_missing untracked &&
255         test_path_is_file tracked
256 '
257
258 test_expect_success 'stash -u -- <tracked> <untracked> clears changes in both' '
259         >tracked &&
260         git add tracked &&
261         >untracked &&
262         git stash push -u -- tracked untracked &&
263         test_path_is_missing tracked &&
264         test_path_is_missing untracked
265 '
266
267 test_expect_success 'stash --all -- <ignored> stashes ignored file' '
268         >ignored.d/bar &&
269         git stash push --all -- ignored.d/bar &&
270         test_path_is_missing ignored.d/bar
271 '
272
273 test_expect_success 'stash --all -- <tracked> <ignored> clears changes in both' '
274         >tracked &&
275         git add tracked &&
276         >ignored.d/bar &&
277         git stash push --all -- tracked ignored.d/bar &&
278         test_path_is_missing tracked &&
279         test_path_is_missing ignored.d/bar
280 '
281
282 test_expect_success 'stash -u -- <ignored> leaves ignored file alone' '
283         >ignored.d/bar &&
284         git stash push -u -- ignored.d/bar &&
285         test_path_is_file ignored.d/bar
286 '
287
288 test_expect_success 'stash -u -- <non-existent> shows no changes when there are none' '
289         git stash push -u -- non-existent >actual &&
290         echo "No local changes to save" >expect &&
291         test_i18ncmp expect actual
292 '
293
294 test_expect_success 'stash -u with globs' '
295         >untracked.txt &&
296         git stash -u -- ":(glob)**/*.txt" &&
297         test_path_is_missing untracked.txt
298 '
299
300 test_expect_success 'stash show --include-untracked shows untracked files' '
301         git reset --hard &&
302         git clean -xf &&
303         >untracked &&
304         >tracked &&
305         git add tracked &&
306         empty_blob_oid=$(git rev-parse --short :tracked) &&
307         git stash -u &&
308
309         cat >expect <<-EOF &&
310          tracked   | 0
311          untracked | 0
312          2 files changed, 0 insertions(+), 0 deletions(-)
313         EOF
314         git stash show --include-untracked >actual &&
315         test_cmp expect actual &&
316         git stash show -u >actual &&
317         test_cmp expect actual &&
318         git stash show --no-include-untracked --include-untracked >actual &&
319         test_cmp expect actual &&
320         git stash show --only-untracked --include-untracked >actual &&
321         test_cmp expect actual &&
322
323         cat >expect <<-EOF &&
324         diff --git a/tracked b/tracked
325         new file mode 100644
326         index 0000000..$empty_blob_oid
327         diff --git a/untracked b/untracked
328         new file mode 100644
329         index 0000000..$empty_blob_oid
330         EOF
331         git stash show -p --include-untracked >actual &&
332         test_cmp expect actual &&
333         git stash show --include-untracked -p >actual &&
334         test_cmp expect actual
335 '
336
337 test_expect_success 'stash show --only-untracked only shows untracked files' '
338         git reset --hard &&
339         git clean -xf &&
340         >untracked &&
341         >tracked &&
342         git add tracked &&
343         empty_blob_oid=$(git rev-parse --short :tracked) &&
344         git stash -u &&
345
346         cat >expect <<-EOF &&
347          untracked | 0
348          1 file changed, 0 insertions(+), 0 deletions(-)
349         EOF
350         git stash show --only-untracked >actual &&
351         test_cmp expect actual &&
352         git stash show --no-include-untracked --only-untracked >actual &&
353         test_cmp expect actual &&
354         git stash show --include-untracked --only-untracked >actual &&
355         test_cmp expect actual &&
356
357         cat >expect <<-EOF &&
358         diff --git a/untracked b/untracked
359         new file mode 100644
360         index 0000000..$empty_blob_oid
361         EOF
362         git stash show -p --only-untracked >actual &&
363         test_cmp expect actual &&
364         git stash show --only-untracked -p >actual &&
365         test_cmp expect actual
366 '
367
368 test_expect_success 'stash show --no-include-untracked cancels --{include,show}-untracked' '
369         git reset --hard &&
370         git clean -xf &&
371         >untracked &&
372         >tracked &&
373         git add tracked &&
374         git stash -u &&
375
376         cat >expect <<-EOF &&
377          tracked | 0
378          1 file changed, 0 insertions(+), 0 deletions(-)
379         EOF
380         git stash show --only-untracked --no-include-untracked >actual &&
381         test_cmp expect actual &&
382         git stash show --include-untracked --no-include-untracked >actual &&
383         test_cmp expect actual
384 '
385
386 test_expect_success 'stash show --include-untracked errors on duplicate files' '
387         git reset --hard &&
388         git clean -xf &&
389         >tracked &&
390         git add tracked &&
391         tree=$(git write-tree) &&
392         i_commit=$(git commit-tree -p HEAD -m "index on any-branch" "$tree") &&
393         test_when_finished "rm -f untracked_index" &&
394         u_commit=$(
395                 GIT_INDEX_FILE="untracked_index" &&
396                 export GIT_INDEX_FILE &&
397                 git update-index --add tracked &&
398                 u_tree=$(git write-tree) &&
399                 git commit-tree -m "untracked files on any-branch" "$u_tree"
400         ) &&
401         w_commit=$(git commit-tree -p HEAD -p "$i_commit" -p "$u_commit" -m "WIP on any-branch" "$tree") &&
402         test_must_fail git stash show --include-untracked "$w_commit" 2>err &&
403         test_i18ngrep "worktree and untracked commit have duplicate entries: tracked" err
404 '
405
406 test_done