1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.api;
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import java.io.File;
19 import java.text.MessageFormat;
20
21 import org.eclipse.jgit.api.errors.InvalidRefNameException;
22 import org.eclipse.jgit.api.errors.JGitInternalException;
23 import org.eclipse.jgit.api.errors.NoHeadException;
24 import org.eclipse.jgit.api.errors.StashApplyFailureException;
25 import org.eclipse.jgit.events.ChangeRecorder;
26 import org.eclipse.jgit.events.ListenerHandle;
27 import org.eclipse.jgit.internal.JGitText;
28 import org.eclipse.jgit.junit.RepositoryTestCase;
29 import org.eclipse.jgit.lib.ObjectId;
30 import org.eclipse.jgit.lib.Repository;
31 import org.eclipse.jgit.merge.ContentMergeStrategy;
32 import org.eclipse.jgit.merge.MergeStrategy;
33 import org.eclipse.jgit.revwalk.RevCommit;
34 import org.eclipse.jgit.util.FileUtils;
35 import org.junit.After;
36 import org.junit.Before;
37 import org.junit.Test;
38
39
40
41
42 public class StashApplyCommandTest extends RepositoryTestCase {
43
44 private static final String PATH = "file.txt";
45
46 private RevCommit head;
47
48 private Git git;
49
50 private File committedFile;
51
52 private ChangeRecorder recorder;
53
54 private ListenerHandle handle;
55
56 @Override
57 @Before
58 public void setUp() throws Exception {
59 super.setUp();
60 git = Git.wrap(db);
61 recorder = new ChangeRecorder();
62 handle = db.getListenerList().addWorkingTreeModifiedListener(recorder);
63 committedFile = writeTrashFile(PATH, "content");
64 git.add().addFilepattern(PATH).call();
65 head = git.commit().setMessage("add file").call();
66 assertNotNull(head);
67 recorder.assertNoEvent();
68 }
69
70 @Override
71 @After
72 public void tearDown() throws Exception {
73 if (handle != null) {
74 handle.remove();
75 }
76 super.tearDown();
77 }
78
79 @Test
80 public void workingDirectoryDelete() throws Exception {
81 deleteTrashFile(PATH);
82 assertFalse(committedFile.exists());
83 RevCommit stashed = git.stashCreate().call();
84 assertNotNull(stashed);
85 assertEquals("content", read(committedFile));
86 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
87
88 ObjectId unstashed = git.stashApply().call();
89 assertEquals(stashed, unstashed);
90 assertFalse(committedFile.exists());
91 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { PATH });
92
93 Status status = git.status().call();
94 assertTrue(status.getAdded().isEmpty());
95 assertTrue(status.getChanged().isEmpty());
96 assertTrue(status.getConflicting().isEmpty());
97 assertTrue(status.getModified().isEmpty());
98 assertTrue(status.getUntracked().isEmpty());
99 assertTrue(status.getRemoved().isEmpty());
100
101 assertEquals(1, status.getMissing().size());
102 assertTrue(status.getMissing().contains(PATH));
103 }
104
105 @Test
106 public void indexAdd() throws Exception {
107 String addedPath = "file2.txt";
108 File addedFile = writeTrashFile(addedPath, "content2");
109 git.add().addFilepattern(addedPath).call();
110
111 RevCommit stashed = git.stashCreate().call();
112 assertNotNull(stashed);
113 assertFalse(addedFile.exists());
114 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { addedPath });
115
116 ObjectId unstashed = git.stashApply().call();
117 assertEquals(stashed, unstashed);
118 assertTrue(addedFile.exists());
119 assertEquals("content2", read(addedFile));
120 recorder.assertEvent(new String[] { addedPath }, ChangeRecorder.EMPTY);
121
122 Status status = git.status().call();
123 assertTrue(status.getChanged().isEmpty());
124 assertTrue(status.getConflicting().isEmpty());
125 assertTrue(status.getMissing().isEmpty());
126 assertTrue(status.getModified().isEmpty());
127 assertTrue(status.getRemoved().isEmpty());
128 assertTrue(status.getUntracked().isEmpty());
129
130 assertEquals(1, status.getAdded().size());
131 assertTrue(status.getAdded().contains(addedPath));
132 }
133
134 @Test
135 public void indexDelete() throws Exception {
136 git.rm().addFilepattern("file.txt").call();
137 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { "file.txt" });
138
139 RevCommit stashed = git.stashCreate().call();
140 assertNotNull(stashed);
141 assertEquals("content", read(committedFile));
142 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
143
144 ObjectId unstashed = git.stashApply().call();
145 assertEquals(stashed, unstashed);
146 assertFalse(committedFile.exists());
147 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { "file.txt" });
148
149 Status status = git.status().call();
150 assertTrue(status.getAdded().isEmpty());
151 assertTrue(status.getChanged().isEmpty());
152 assertTrue(status.getConflicting().isEmpty());
153 assertTrue(status.getModified().isEmpty());
154 assertTrue(status.getMissing().isEmpty());
155 assertTrue(status.getUntracked().isEmpty());
156
157 assertEquals(1, status.getRemoved().size());
158 assertTrue(status.getRemoved().contains(PATH));
159 }
160
161 @Test
162 public void workingDirectoryModify() throws Exception {
163 writeTrashFile("file.txt", "content2");
164
165 RevCommit stashed = git.stashCreate().call();
166 assertNotNull(stashed);
167 assertEquals("content", read(committedFile));
168 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
169
170 ObjectId unstashed = git.stashApply().call();
171 assertEquals(stashed, unstashed);
172 assertEquals("content2", read(committedFile));
173 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
174
175 Status status = git.status().call();
176 assertTrue(status.getAdded().isEmpty());
177 assertTrue(status.getChanged().isEmpty());
178 assertTrue(status.getConflicting().isEmpty());
179 assertTrue(status.getMissing().isEmpty());
180 assertTrue(status.getRemoved().isEmpty());
181 assertTrue(status.getUntracked().isEmpty());
182
183 assertEquals(1, status.getModified().size());
184 assertTrue(status.getModified().contains(PATH));
185 }
186
187 @Test
188 public void workingDirectoryModifyInSubfolder() throws Exception {
189 String path = "d1/d2/f.txt";
190 File subfolderFile = writeTrashFile(path, "content");
191 git.add().addFilepattern(path).call();
192 head = git.commit().setMessage("add file").call();
193 recorder.assertNoEvent();
194
195 writeTrashFile(path, "content2");
196
197 RevCommit stashed = git.stashCreate().call();
198 assertNotNull(stashed);
199 assertEquals("content", read(subfolderFile));
200 recorder.assertEvent(new String[] { "d1/d2/f.txt" },
201 ChangeRecorder.EMPTY);
202
203 ObjectId unstashed = git.stashApply().call();
204 assertEquals(stashed, unstashed);
205 assertEquals("content2", read(subfolderFile));
206 recorder.assertEvent(new String[] { "d1/d2/f.txt" },
207 ChangeRecorder.EMPTY);
208
209 Status status = git.status().call();
210 assertTrue(status.getAdded().isEmpty());
211 assertTrue(status.getChanged().isEmpty());
212 assertTrue(status.getConflicting().isEmpty());
213 assertTrue(status.getMissing().isEmpty());
214 assertTrue(status.getRemoved().isEmpty());
215 assertTrue(status.getUntracked().isEmpty());
216
217 assertEquals(1, status.getModified().size());
218 assertTrue(status.getModified().contains(path));
219 }
220
221 @Test
222 public void workingDirectoryModifyIndexChanged() throws Exception {
223 writeTrashFile("file.txt", "content2");
224 git.add().addFilepattern("file.txt").call();
225 writeTrashFile("file.txt", "content3");
226
227 RevCommit stashed = git.stashCreate().call();
228 assertNotNull(stashed);
229 assertEquals("content", read(committedFile));
230 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
231
232 ObjectId unstashed = git.stashApply().call();
233 assertEquals(stashed, unstashed);
234 assertEquals("content3", read(committedFile));
235 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
236
237 Status status = git.status().call();
238 assertTrue(status.getAdded().isEmpty());
239 assertTrue(status.getConflicting().isEmpty());
240 assertTrue(status.getMissing().isEmpty());
241 assertTrue(status.getRemoved().isEmpty());
242 assertTrue(status.getUntracked().isEmpty());
243
244 assertEquals(1, status.getChanged().size());
245 assertTrue(status.getChanged().contains(PATH));
246 assertEquals(1, status.getModified().size());
247 assertTrue(status.getModified().contains(PATH));
248 }
249
250 @Test
251 public void workingDirectoryCleanIndexModify() throws Exception {
252 writeTrashFile("file.txt", "content2");
253 git.add().addFilepattern("file.txt").call();
254 writeTrashFile("file.txt", "content");
255
256 RevCommit stashed = git.stashCreate().call();
257 assertNotNull(stashed);
258 assertEquals("content", read(committedFile));
259 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
260
261 ObjectId unstashed = git.stashApply().call();
262 assertEquals(stashed, unstashed);
263 assertEquals("content2", read(committedFile));
264 recorder.assertEvent(new String[] { "file.txt" }, ChangeRecorder.EMPTY);
265
266 Status status = git.status().call();
267 assertTrue(status.getAdded().isEmpty());
268 assertTrue(status.getConflicting().isEmpty());
269 assertTrue(status.getMissing().isEmpty());
270 assertTrue(status.getModified().isEmpty());
271 assertTrue(status.getRemoved().isEmpty());
272 assertTrue(status.getUntracked().isEmpty());
273
274 assertEquals(1, status.getChanged().size());
275 assertTrue(status.getChanged().contains(PATH));
276 }
277
278 @Test
279 public void workingDirectoryDeleteIndexAdd() throws Exception {
280 String path = "file2.txt";
281 File added = writeTrashFile(path, "content2");
282 assertTrue(added.exists());
283 git.add().addFilepattern(path).call();
284 FileUtils.delete(added);
285 assertFalse(added.exists());
286
287 RevCommit stashed = git.stashCreate().call();
288 assertNotNull(stashed);
289 assertFalse(added.exists());
290 recorder.assertNoEvent();
291
292 ObjectId unstashed = git.stashApply().call();
293 assertEquals(stashed, unstashed);
294 assertEquals("content2", read(added));
295 recorder.assertEvent(new String[] { path }, ChangeRecorder.EMPTY);
296
297 Status status = git.status().call();
298 assertTrue(status.getChanged().isEmpty());
299 assertTrue(status.getConflicting().isEmpty());
300 assertTrue(status.getMissing().isEmpty());
301 assertTrue(status.getModified().isEmpty());
302 assertTrue(status.getRemoved().isEmpty());
303 assertTrue(status.getUntracked().isEmpty());
304
305 assertEquals(1, status.getAdded().size());
306 assertTrue(status.getAdded().contains(path));
307 }
308
309 @Test
310 public void workingDirectoryDeleteIndexEdit() throws Exception {
311 writeTrashFile(PATH, "content2");
312 git.add().addFilepattern(PATH).call();
313 FileUtils.delete(committedFile);
314 assertFalse(committedFile.exists());
315
316 RevCommit stashed = git.stashCreate().call();
317 assertNotNull(stashed);
318 assertEquals("content", read(committedFile));
319 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
320
321 ObjectId unstashed = git.stashApply().call();
322 assertEquals(stashed, unstashed);
323 assertFalse(committedFile.exists());
324 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { PATH });
325
326 Status status = git.status().call();
327 assertTrue(status.getAdded().isEmpty());
328 assertEquals(1, status.getChanged().size());
329 assertTrue(status.getChanged().contains(PATH));
330 assertTrue(status.getConflicting().isEmpty());
331 assertEquals(1, status.getMissing().size());
332 assertTrue(status.getMissing().contains(PATH));
333 assertTrue(status.getModified().isEmpty());
334 assertTrue(status.getUntracked().isEmpty());
335
336 assertTrue(status.getRemoved().isEmpty());
337 }
338
339 @Test
340 public void multipleEdits() throws Exception {
341 String addedPath = "file2.txt";
342 git.rm().addFilepattern(PATH).call();
343 File addedFile = writeTrashFile(addedPath, "content2");
344 git.add().addFilepattern(addedPath).call();
345
346 RevCommit stashed = git.stashCreate().call();
347 assertNotNull(stashed);
348 assertTrue(committedFile.exists());
349 assertFalse(addedFile.exists());
350 recorder.assertEvent(new String[] { PATH },
351 new String[] { "file2.txt" });
352
353 ObjectId unstashed = git.stashApply().call();
354 assertEquals(stashed, unstashed);
355 recorder.assertEvent(new String[] { "file2.txt" },
356 new String[] { PATH });
357
358 Status status = git.status().call();
359 assertTrue(status.getChanged().isEmpty());
360 assertTrue(status.getConflicting().isEmpty());
361 assertTrue(status.getMissing().isEmpty());
362 assertTrue(status.getModified().isEmpty());
363 assertTrue(status.getUntracked().isEmpty());
364
365 assertEquals(1, status.getRemoved().size());
366 assertTrue(status.getRemoved().contains(PATH));
367 assertEquals(1, status.getAdded().size());
368 assertTrue(status.getAdded().contains(addedPath));
369 }
370
371 @Test
372 public void workingDirectoryContentConflict() throws Exception {
373 writeTrashFile(PATH, "content2");
374
375 RevCommit stashed = git.stashCreate().call();
376 assertNotNull(stashed);
377 assertEquals("content", read(committedFile));
378 assertTrue(git.status().call().isClean());
379 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
380
381 writeTrashFile(PATH, "content3");
382
383 try {
384 git.stashApply().call();
385 fail("Exception not thrown");
386 } catch (StashApplyFailureException e) {
387
388 }
389 assertEquals("content3", read(PATH));
390 recorder.assertNoEvent();
391 }
392
393 @Test
394 public void stashedContentMerge() throws Exception {
395 writeTrashFile(PATH, "content\nmore content\n");
396 git.add().addFilepattern(PATH).call();
397 git.commit().setMessage("more content").call();
398
399 writeTrashFile(PATH, "content\nhead change\nmore content\n");
400 git.add().addFilepattern(PATH).call();
401 git.commit().setMessage("even content").call();
402
403 writeTrashFile(PATH, "content\nstashed change\nmore content\n");
404
405 RevCommit stashed = git.stashCreate().call();
406 assertNotNull(stashed);
407 assertEquals("content\nhead change\nmore content\n",
408 read(committedFile));
409 assertTrue(git.status().call().isClean());
410 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
411
412 writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
413 git.add().addFilepattern(PATH).call();
414 git.commit().setMessage("committed change").call();
415 recorder.assertNoEvent();
416
417 try {
418 git.stashApply().call();
419 fail("Expected conflict");
420 } catch (StashApplyFailureException e) {
421
422 }
423 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
424 Status status = new StatusCommand(db).call();
425 assertEquals(1, status.getConflicting().size());
426 assertEquals(
427 "content\n<<<<<<< HEAD\n=======\nstashed change\n>>>>>>> stash\nmore content\ncommitted change\n",
428 read(PATH));
429 }
430
431 @Test
432 public void stashedContentMergeXtheirs() throws Exception {
433 writeTrashFile(PATH, "content\nmore content\n");
434 git.add().addFilepattern(PATH).call();
435 git.commit().setMessage("more content").call();
436
437 writeTrashFile(PATH, "content\nhead change\nmore content\n");
438 git.add().addFilepattern(PATH).call();
439 git.commit().setMessage("even content").call();
440
441 writeTrashFile(PATH, "content\nstashed change\nmore content\n");
442
443 RevCommit stashed = git.stashCreate().call();
444 assertNotNull(stashed);
445 assertEquals("content\nhead change\nmore content\n",
446 read(committedFile));
447 assertTrue(git.status().call().isClean());
448 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
449
450 writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
451 git.add().addFilepattern(PATH).call();
452 git.commit().setMessage("committed change").call();
453 recorder.assertNoEvent();
454
455 git.stashApply().setContentMergeStrategy(ContentMergeStrategy.THEIRS)
456 .call();
457 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
458 Status status = new StatusCommand(db).call();
459 assertEquals('[' + PATH + ']', status.getModified().toString());
460 assertEquals(
461 "content\nstashed change\nmore content\ncommitted change\n",
462 read(PATH));
463 }
464
465 @Test
466 public void stashedContentMergeXours() throws Exception {
467 writeTrashFile(PATH, "content\nmore content\n");
468 git.add().addFilepattern(PATH).call();
469 git.commit().setMessage("more content").call();
470
471 writeTrashFile(PATH, "content\nhead change\nmore content\n");
472 git.add().addFilepattern(PATH).call();
473 git.commit().setMessage("even content").call();
474
475 writeTrashFile(PATH, "content\nstashed change\nmore content\n");
476
477 RevCommit stashed = git.stashCreate().call();
478 assertNotNull(stashed);
479 assertEquals("content\nhead change\nmore content\n",
480 read(committedFile));
481 assertTrue(git.status().call().isClean());
482 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
483
484 writeTrashFile(PATH,
485 "content\nnew head\nmore content\ncommitted change\n");
486 git.add().addFilepattern(PATH).call();
487 git.commit().setMessage("committed change").call();
488 recorder.assertNoEvent();
489
490 git.stashApply().setContentMergeStrategy(ContentMergeStrategy.OURS)
491 .call();
492 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
493 assertTrue(git.status().call().isClean());
494 assertEquals("content\nnew head\nmore content\ncommitted change\n",
495 read(PATH));
496 }
497
498 @Test
499 public void stashedContentMergeTheirs() throws Exception {
500 writeTrashFile(PATH, "content\nmore content\n");
501 git.add().addFilepattern(PATH).call();
502 git.commit().setMessage("more content").call();
503
504 writeTrashFile(PATH, "content\nhead change\nmore content\n");
505 git.add().addFilepattern(PATH).call();
506 git.commit().setMessage("even content").call();
507
508 writeTrashFile(PATH, "content\nstashed change\nmore content\n");
509
510 RevCommit stashed = git.stashCreate().call();
511 assertNotNull(stashed);
512 assertEquals("content\nhead change\nmore content\n",
513 read(committedFile));
514 assertTrue(git.status().call().isClean());
515 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
516
517 writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
518 git.add().addFilepattern(PATH).call();
519 git.commit().setMessage("committed change").call();
520 recorder.assertNoEvent();
521
522 git.stashApply().setStrategy(MergeStrategy.THEIRS).call();
523 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
524 Status status = new StatusCommand(db).call();
525 assertEquals('[' + PATH + ']', status.getModified().toString());
526 assertEquals("content\nstashed change\nmore content\n", read(PATH));
527 }
528
529 @Test
530 public void stashedContentMergeOurs() throws Exception {
531 writeTrashFile(PATH, "content\nmore content\n");
532 git.add().addFilepattern(PATH).call();
533 git.commit().setMessage("more content").call();
534
535 writeTrashFile(PATH, "content\nhead change\nmore content\n");
536 git.add().addFilepattern(PATH).call();
537 git.commit().setMessage("even content").call();
538
539 writeTrashFile(PATH, "content\nstashed change\nmore content\n");
540
541 RevCommit stashed = git.stashCreate().call();
542 assertNotNull(stashed);
543 assertEquals("content\nhead change\nmore content\n",
544 read(committedFile));
545 assertTrue(git.status().call().isClean());
546 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
547
548 writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
549 git.add().addFilepattern(PATH).call();
550 git.commit().setMessage("committed change").call();
551 recorder.assertNoEvent();
552
553
554 git.stashApply().setStrategy(MergeStrategy.OURS).call();
555 recorder.assertNoEvent();
556 assertTrue(git.status().call().isClean());
557 assertEquals("content\nmore content\ncommitted change\n", read(PATH));
558 }
559
560 @Test
561 public void stashedApplyOnOtherBranch() throws Exception {
562 writeTrashFile(PATH, "content\nmore content\n");
563 git.add().addFilepattern(PATH).call();
564 git.commit().setMessage("more content").call();
565 String path2 = "file2.txt";
566 File file2 = writeTrashFile(path2, "content\nmore content\n");
567 git.add().addFilepattern(PATH).call();
568 git.add().addFilepattern(path2).call();
569 git.commit().setMessage("even content").call();
570
571 String otherBranch = "otherBranch";
572 git.branchCreate().setName(otherBranch).call();
573
574 writeTrashFile(PATH, "master content");
575 git.add().addFilepattern(PATH).call();
576 git.commit().setMessage("even content").call();
577 recorder.assertNoEvent();
578
579 git.checkout().setName(otherBranch).call();
580 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
581
582 writeTrashFile(PATH, "otherBranch content");
583 git.add().addFilepattern(PATH).call();
584 git.commit().setMessage("even more content").call();
585 recorder.assertNoEvent();
586
587 writeTrashFile(path2, "content\nstashed change\nmore content\n");
588
589 RevCommit stashed = git.stashCreate().call();
590
591 assertNotNull(stashed);
592 assertEquals("content\nmore content\n", read(file2));
593 assertEquals("otherBranch content",
594 read(committedFile));
595 assertTrue(git.status().call().isClean());
596 recorder.assertEvent(new String[] { path2 }, ChangeRecorder.EMPTY);
597
598 git.checkout().setName("master").call();
599 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
600 git.stashApply().call();
601 assertEquals("content\nstashed change\nmore content\n", read(file2));
602 assertEquals("master content",
603 read(committedFile));
604 recorder.assertEvent(new String[] { path2 }, ChangeRecorder.EMPTY);
605 }
606
607 @Test
608 public void stashedApplyOnOtherBranchWithStagedChange() throws Exception {
609 writeTrashFile(PATH, "content\nmore content\n");
610 git.add().addFilepattern(PATH).call();
611 git.commit().setMessage("more content").call();
612 String path2 = "file2.txt";
613 File file2 = writeTrashFile(path2, "content\nmore content\n");
614 git.add().addFilepattern(PATH).call();
615 git.add().addFilepattern(path2).call();
616 git.commit().setMessage("even content").call();
617
618 String otherBranch = "otherBranch";
619 git.branchCreate().setName(otherBranch).call();
620
621 writeTrashFile(PATH, "master content");
622 git.add().addFilepattern(PATH).call();
623 git.commit().setMessage("even content").call();
624 recorder.assertNoEvent();
625
626 git.checkout().setName(otherBranch).call();
627 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
628
629 writeTrashFile(PATH, "otherBranch content");
630 git.add().addFilepattern(PATH).call();
631 git.commit().setMessage("even more content").call();
632 recorder.assertNoEvent();
633
634 writeTrashFile(path2,
635 "content\nstashed change in index\nmore content\n");
636 git.add().addFilepattern(path2).call();
637 writeTrashFile(path2, "content\nstashed change\nmore content\n");
638
639 RevCommit stashed = git.stashCreate().call();
640
641 assertNotNull(stashed);
642 assertEquals("content\nmore content\n", read(file2));
643 assertEquals("otherBranch content", read(committedFile));
644 assertTrue(git.status().call().isClean());
645 recorder.assertEvent(new String[] { path2 }, ChangeRecorder.EMPTY);
646
647 git.checkout().setName("master").call();
648 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
649 git.stashApply().call();
650 assertEquals("content\nstashed change\nmore content\n", read(file2));
651 assertEquals(
652 "[file.txt, mode:100644, content:master content]"
653 + "[file2.txt, mode:100644, content:content\nstashed change in index\nmore content\n]",
654 indexState(CONTENT));
655 assertEquals("master content", read(committedFile));
656 recorder.assertEvent(new String[] { path2 }, ChangeRecorder.EMPTY);
657 }
658
659 @Test
660 public void workingDirectoryContentMerge() throws Exception {
661 writeTrashFile(PATH, "content\nmore content\n");
662 git.add().addFilepattern(PATH).call();
663 git.commit().setMessage("more content").call();
664 recorder.assertNoEvent();
665
666 writeTrashFile(PATH, "content\nstashed change\nmore content\n");
667
668 RevCommit stashed = git.stashCreate().call();
669 assertNotNull(stashed);
670 assertEquals("content\nmore content\n", read(committedFile));
671 assertTrue(git.status().call().isClean());
672 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
673
674 writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
675 git.add().addFilepattern(PATH).call();
676 git.commit().setMessage("committed change").call();
677 recorder.assertNoEvent();
678
679 git.stashApply().call();
680 assertEquals(
681 "content\nstashed change\nmore content\ncommitted change\n",
682 read(committedFile));
683 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
684 }
685
686 @Test
687 public void indexContentConflict() throws Exception {
688 writeTrashFile(PATH, "content2");
689
690 RevCommit stashed = git.stashCreate().call();
691 assertNotNull(stashed);
692 assertEquals("content", read(committedFile));
693 assertTrue(git.status().call().isClean());
694 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
695
696 writeTrashFile(PATH, "content3");
697 git.add().addFilepattern(PATH).call();
698 writeTrashFile(PATH, "content2");
699
700 try {
701 git.stashApply().call();
702 fail("Exception not thrown");
703 } catch (StashApplyFailureException e) {
704
705 }
706 recorder.assertNoEvent();
707 assertEquals("content2", read(PATH));
708 }
709
710 @Test
711 public void workingDirectoryEditPreCommit() throws Exception {
712 writeTrashFile(PATH, "content2");
713
714 RevCommit stashed = git.stashCreate().call();
715 assertNotNull(stashed);
716 assertEquals("content", read(committedFile));
717 assertTrue(git.status().call().isClean());
718 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
719
720 String path2 = "file2.txt";
721 writeTrashFile(path2, "content3");
722 git.add().addFilepattern(path2).call();
723 assertNotNull(git.commit().setMessage("adding file").call());
724
725 ObjectId unstashed = git.stashApply().call();
726 assertEquals(stashed, unstashed);
727 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
728
729 Status status = git.status().call();
730 assertTrue(status.getAdded().isEmpty());
731 assertTrue(status.getChanged().isEmpty());
732 assertTrue(status.getConflicting().isEmpty());
733 assertTrue(status.getMissing().isEmpty());
734 assertTrue(status.getRemoved().isEmpty());
735 assertTrue(status.getUntracked().isEmpty());
736
737 assertEquals(1, status.getModified().size());
738 assertTrue(status.getModified().contains(PATH));
739 }
740
741 @Test
742 public void stashChangeInANewSubdirectory() throws Exception {
743 String subdir = "subdir";
744 String fname = "file2.txt";
745 String path = subdir + "/" + fname;
746 String otherBranch = "otherbranch";
747
748 writeTrashFile(subdir, fname, "content2");
749
750 git.add().addFilepattern(path).call();
751 RevCommit stashed = git.stashCreate().call();
752 assertNotNull(stashed);
753 assertTrue(git.status().call().isClean());
754 recorder.assertEvent(ChangeRecorder.EMPTY,
755 new String[] { subdir, path });
756
757 git.branchCreate().setName(otherBranch).call();
758 git.checkout().setName(otherBranch).call();
759
760 ObjectId unstashed = git.stashApply().call();
761 assertEquals(stashed, unstashed);
762 recorder.assertEvent(new String[] { path }, ChangeRecorder.EMPTY);
763
764 Status status = git.status().call();
765 assertTrue(status.getChanged().isEmpty());
766 assertTrue(status.getConflicting().isEmpty());
767 assertTrue(status.getMissing().isEmpty());
768 assertTrue(status.getRemoved().isEmpty());
769 assertTrue(status.getModified().isEmpty());
770 assertTrue(status.getUntracked().isEmpty());
771
772 assertEquals(1, status.getAdded().size());
773 assertTrue(status.getAdded().contains(path));
774 }
775
776 @Test
777 public void unstashNonStashCommit() throws Exception {
778 try {
779 git.stashApply().setStashRef(head.name()).call();
780 fail("Exception not thrown");
781 } catch (JGitInternalException e) {
782 assertEquals(MessageFormat.format(
783 JGitText.get().stashCommitIncorrectNumberOfParents,
784 head.name(), "0"),
785 e.getMessage());
786 }
787 }
788
789 @Test
790 public void unstashNoHead() throws Exception {
791 Repository repo = createWorkRepository();
792 try {
793 Git.wrap(repo).stashApply().call();
794 fail("Exception not thrown");
795 } catch (NoHeadException e) {
796 assertNotNull(e.getMessage());
797 }
798 }
799
800 @Test
801 public void noStashedCommits() throws Exception {
802 try {
803 git.stashApply().call();
804 fail("Exception not thrown");
805 } catch (InvalidRefNameException e) {
806 assertNotNull(e.getMessage());
807 }
808 }
809
810 @Test
811 public void testApplyStashWithDeletedFile() throws Exception {
812 File file = writeTrashFile("file", "content");
813 git.add().addFilepattern("file").call();
814 git.commit().setMessage("x").call();
815 file.delete();
816 git.rm().addFilepattern("file").call();
817 recorder.assertNoEvent();
818 git.stashCreate().call();
819 recorder.assertEvent(new String[] { "file" }, ChangeRecorder.EMPTY);
820 file.delete();
821
822 git.stashApply().setStashRef("stash@{0}").call();
823
824 assertFalse(file.exists());
825 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { "file" });
826 }
827
828 @Test
829 public void untrackedFileNotIncluded() throws Exception {
830 String untrackedPath = "untracked.txt";
831 File untrackedFile = writeTrashFile(untrackedPath, "content");
832
833 writeTrashFile(PATH, "content2");
834 git.add().addFilepattern(PATH).call();
835 git.stashCreate().call();
836 assertTrue(untrackedFile.exists());
837 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
838
839 git.stashApply().setStashRef("stash@{0}").call();
840 assertTrue(untrackedFile.exists());
841 recorder.assertEvent(new String[] { PATH }, ChangeRecorder.EMPTY);
842
843 Status status = git.status().call();
844 assertEquals(1, status.getUntracked().size());
845 assertTrue(status.getUntracked().contains(untrackedPath));
846 assertEquals(1, status.getChanged().size());
847 assertTrue(status.getChanged().contains(PATH));
848 assertTrue(status.getAdded().isEmpty());
849 assertTrue(status.getConflicting().isEmpty());
850 assertTrue(status.getMissing().isEmpty());
851 assertTrue(status.getRemoved().isEmpty());
852 assertTrue(status.getModified().isEmpty());
853 }
854
855 @Test
856 public void untrackedFileIncluded() throws Exception {
857 String path = "a/b/untracked.txt";
858 File untrackedFile = writeTrashFile(path, "content");
859 RevCommit stashedCommit = git.stashCreate().setIncludeUntracked(true)
860 .call();
861 assertNotNull(stashedCommit);
862 assertFalse(untrackedFile.exists());
863 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { path });
864
865 deleteTrashFile("a/b");
866
867 git.stashApply().setStashRef("stash@{0}").call();
868 assertTrue(untrackedFile.exists());
869 assertEquals("content", read(path));
870 recorder.assertEvent(new String[] { path }, ChangeRecorder.EMPTY);
871
872 Status status = git.status().call();
873 assertEquals(1, status.getUntracked().size());
874 assertTrue(status.getAdded().isEmpty());
875 assertTrue(status.getChanged().isEmpty());
876 assertTrue(status.getConflicting().isEmpty());
877 assertTrue(status.getMissing().isEmpty());
878 assertTrue(status.getRemoved().isEmpty());
879 assertTrue(status.getModified().isEmpty());
880 assertTrue(status.getUntracked().contains(path));
881 }
882
883 @Test
884 public void untrackedFileConflictsWithCommit() throws Exception {
885 String path = "untracked.txt";
886 writeTrashFile(path, "untracked");
887 git.stashCreate().setIncludeUntracked(true).call();
888 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { path });
889
890 writeTrashFile(path, "committed");
891 head = git.commit().setMessage("add file").call();
892 git.add().addFilepattern(path).call();
893 git.commit().setMessage("conflicting commit").call();
894
895 try {
896 git.stashApply().setStashRef("stash@{0}").call();
897 fail("StashApplyFailureException should be thrown.");
898 } catch (StashApplyFailureException e) {
899 assertEquals(e.getMessage(), JGitText.get().stashApplyConflict);
900 }
901 assertEquals("committed", read(path));
902 recorder.assertNoEvent();
903 }
904
905 @Test
906 public void untrackedFileConflictsWithWorkingDirectory()
907 throws Exception {
908 String path = "untracked.txt";
909 writeTrashFile(path, "untracked");
910 git.stashCreate().setIncludeUntracked(true).call();
911 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { path });
912
913 writeTrashFile(path, "working-directory");
914 try {
915 git.stashApply().setStashRef("stash@{0}").call();
916 fail("StashApplyFailureException should be thrown.");
917 } catch (StashApplyFailureException e) {
918 assertEquals(e.getMessage(), JGitText.get().stashApplyConflict);
919 }
920 assertEquals("working-directory", read(path));
921 recorder.assertNoEvent();
922 }
923
924 @Test
925 public void untrackedAndTrackedChanges() throws Exception {
926 writeTrashFile(PATH, "changed");
927 String path = "untracked.txt";
928 writeTrashFile(path, "untracked");
929 git.stashCreate().setIncludeUntracked(true).call();
930 assertTrue(PATH + " should exist", check(PATH));
931 assertEquals(PATH + " should have been reset", "content", read(PATH));
932 assertFalse(path + " should not exist", check(path));
933 recorder.assertEvent(new String[] { PATH }, new String[] { path });
934 git.stashApply().setStashRef("stash@{0}").call();
935 assertTrue(PATH + " should exist", check(PATH));
936 assertEquals(PATH + " should have new content", "changed", read(PATH));
937 assertTrue(path + " should exist", check(path));
938 assertEquals(path + " should have new content", "untracked",
939 read(path));
940 recorder.assertEvent(new String[] { PATH, path }, ChangeRecorder.EMPTY);
941 }
942 }