View Javadoc
1   /*
2    * Copyright (C) 2012, GitHub Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  package org.eclipse.jgit.api;
44  
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.assertFalse;
47  import static org.junit.Assert.assertNotNull;
48  import static org.junit.Assert.assertTrue;
49  import static org.junit.Assert.fail;
50  
51  import java.io.File;
52  import java.text.MessageFormat;
53  
54  import org.eclipse.jgit.api.errors.InvalidRefNameException;
55  import org.eclipse.jgit.api.errors.JGitInternalException;
56  import org.eclipse.jgit.api.errors.NoHeadException;
57  import org.eclipse.jgit.api.errors.StashApplyFailureException;
58  import org.eclipse.jgit.internal.JGitText;
59  import org.eclipse.jgit.junit.RepositoryTestCase;
60  import org.eclipse.jgit.lib.ObjectId;
61  import org.eclipse.jgit.lib.Repository;
62  import org.eclipse.jgit.revwalk.RevCommit;
63  import org.eclipse.jgit.util.FileUtils;
64  import org.junit.Before;
65  import org.junit.Test;
66  
67  /**
68   * Unit tests of {@link StashApplyCommand}
69   */
70  public class StashApplyCommandTest extends RepositoryTestCase {
71  
72  	private static final String PATH = "file.txt";
73  
74  	private RevCommit head;
75  
76  	private Git git;
77  
78  	private File committedFile;
79  
80  	@Before
81  	public void setUp() throws Exception {
82  		super.setUp();
83  		git = Git.wrap(db);
84  		committedFile = writeTrashFile(PATH, "content");
85  		git.add().addFilepattern(PATH).call();
86  		head = git.commit().setMessage("add file").call();
87  		assertNotNull(head);
88  	}
89  
90  	@Test
91  	public void workingDirectoryDelete() throws Exception {
92  		deleteTrashFile(PATH);
93  		assertFalse(committedFile.exists());
94  		RevCommit stashed = git.stashCreate().call();
95  		assertNotNull(stashed);
96  		assertEquals("content", read(committedFile));
97  
98  		ObjectId unstashed = git.stashApply().call();
99  		assertEquals(stashed, unstashed);
100 		assertFalse(committedFile.exists());
101 
102 		Status status = git.status().call();
103 		assertTrue(status.getAdded().isEmpty());
104 		assertTrue(status.getChanged().isEmpty());
105 		assertTrue(status.getConflicting().isEmpty());
106 		assertTrue(status.getModified().isEmpty());
107 		assertTrue(status.getUntracked().isEmpty());
108 		assertTrue(status.getRemoved().isEmpty());
109 
110 		assertEquals(1, status.getMissing().size());
111 		assertTrue(status.getMissing().contains(PATH));
112 	}
113 
114 	@Test
115 	public void indexAdd() throws Exception {
116 		String addedPath = "file2.txt";
117 		File addedFile = writeTrashFile(addedPath, "content2");
118 		git.add().addFilepattern(addedPath).call();
119 
120 		RevCommit stashed = git.stashCreate().call();
121 		assertNotNull(stashed);
122 		assertFalse(addedFile.exists());
123 
124 		ObjectId unstashed = git.stashApply().call();
125 		assertEquals(stashed, unstashed);
126 		assertTrue(addedFile.exists());
127 		assertEquals("content2", read(addedFile));
128 
129 		Status status = git.status().call();
130 		assertTrue(status.getChanged().isEmpty());
131 		assertTrue(status.getConflicting().isEmpty());
132 		assertTrue(status.getMissing().isEmpty());
133 		assertTrue(status.getModified().isEmpty());
134 		assertTrue(status.getRemoved().isEmpty());
135 		assertTrue(status.getUntracked().isEmpty());
136 
137 		assertEquals(1, status.getAdded().size());
138 		assertTrue(status.getAdded().contains(addedPath));
139 	}
140 
141 	@Test
142 	public void indexDelete() throws Exception {
143 		git.rm().addFilepattern("file.txt").call();
144 
145 		RevCommit stashed = git.stashCreate().call();
146 		assertNotNull(stashed);
147 		assertEquals("content", read(committedFile));
148 
149 		ObjectId unstashed = git.stashApply().call();
150 		assertEquals(stashed, unstashed);
151 		assertFalse(committedFile.exists());
152 
153 		Status status = git.status().call();
154 		assertTrue(status.getAdded().isEmpty());
155 		assertTrue(status.getChanged().isEmpty());
156 		assertTrue(status.getConflicting().isEmpty());
157 		assertTrue(status.getModified().isEmpty());
158 		assertTrue(status.getMissing().isEmpty());
159 		assertTrue(status.getUntracked().isEmpty());
160 
161 		assertEquals(1, status.getRemoved().size());
162 		assertTrue(status.getRemoved().contains(PATH));
163 	}
164 
165 	@Test
166 	public void workingDirectoryModify() throws Exception {
167 		writeTrashFile("file.txt", "content2");
168 
169 		RevCommit stashed = git.stashCreate().call();
170 		assertNotNull(stashed);
171 		assertEquals("content", read(committedFile));
172 
173 		ObjectId unstashed = git.stashApply().call();
174 		assertEquals(stashed, unstashed);
175 		assertEquals("content2", read(committedFile));
176 
177 		Status status = git.status().call();
178 		assertTrue(status.getAdded().isEmpty());
179 		assertTrue(status.getChanged().isEmpty());
180 		assertTrue(status.getConflicting().isEmpty());
181 		assertTrue(status.getMissing().isEmpty());
182 		assertTrue(status.getRemoved().isEmpty());
183 		assertTrue(status.getUntracked().isEmpty());
184 
185 		assertEquals(1, status.getModified().size());
186 		assertTrue(status.getModified().contains(PATH));
187 	}
188 
189 	@Test
190 	public void workingDirectoryModifyInSubfolder() throws Exception {
191 		String path = "d1/d2/f.txt";
192 		File subfolderFile = writeTrashFile(path, "content");
193 		git.add().addFilepattern(path).call();
194 		head = git.commit().setMessage("add file").call();
195 
196 		writeTrashFile(path, "content2");
197 
198 		RevCommit stashed = git.stashCreate().call();
199 		assertNotNull(stashed);
200 		assertEquals("content", read(subfolderFile));
201 
202 		ObjectId unstashed = git.stashApply().call();
203 		assertEquals(stashed, unstashed);
204 		assertEquals("content2", read(subfolderFile));
205 
206 		Status status = git.status().call();
207 		assertTrue(status.getAdded().isEmpty());
208 		assertTrue(status.getChanged().isEmpty());
209 		assertTrue(status.getConflicting().isEmpty());
210 		assertTrue(status.getMissing().isEmpty());
211 		assertTrue(status.getRemoved().isEmpty());
212 		assertTrue(status.getUntracked().isEmpty());
213 
214 		assertEquals(1, status.getModified().size());
215 		assertTrue(status.getModified().contains(path));
216 	}
217 
218 	@Test
219 	public void workingDirectoryModifyIndexChanged() throws Exception {
220 		writeTrashFile("file.txt", "content2");
221 		git.add().addFilepattern("file.txt").call();
222 		writeTrashFile("file.txt", "content3");
223 
224 		RevCommit stashed = git.stashCreate().call();
225 		assertNotNull(stashed);
226 		assertEquals("content", read(committedFile));
227 
228 		ObjectId unstashed = git.stashApply().call();
229 		assertEquals(stashed, unstashed);
230 		assertEquals("content3", read(committedFile));
231 
232 		Status status = git.status().call();
233 		assertTrue(status.getAdded().isEmpty());
234 		assertTrue(status.getConflicting().isEmpty());
235 		assertTrue(status.getMissing().isEmpty());
236 		assertTrue(status.getRemoved().isEmpty());
237 		assertTrue(status.getUntracked().isEmpty());
238 
239 		assertEquals(1, status.getChanged().size());
240 		assertTrue(status.getChanged().contains(PATH));
241 		assertEquals(1, status.getModified().size());
242 		assertTrue(status.getModified().contains(PATH));
243 	}
244 
245 	@Test
246 	public void workingDirectoryCleanIndexModify() throws Exception {
247 		writeTrashFile("file.txt", "content2");
248 		git.add().addFilepattern("file.txt").call();
249 		writeTrashFile("file.txt", "content");
250 
251 		RevCommit stashed = git.stashCreate().call();
252 		assertNotNull(stashed);
253 		assertEquals("content", read(committedFile));
254 
255 		ObjectId unstashed = git.stashApply().call();
256 		assertEquals(stashed, unstashed);
257 		assertEquals("content2", read(committedFile));
258 
259 		Status status = git.status().call();
260 		assertTrue(status.getAdded().isEmpty());
261 		assertTrue(status.getConflicting().isEmpty());
262 		assertTrue(status.getMissing().isEmpty());
263 		assertTrue(status.getModified().isEmpty());
264 		assertTrue(status.getRemoved().isEmpty());
265 		assertTrue(status.getUntracked().isEmpty());
266 
267 		assertEquals(1, status.getChanged().size());
268 		assertTrue(status.getChanged().contains(PATH));
269 	}
270 
271 	@Test
272 	public void workingDirectoryDeleteIndexAdd() throws Exception {
273 		String path = "file2.txt";
274 		File added = writeTrashFile(path, "content2");
275 		assertTrue(added.exists());
276 		git.add().addFilepattern(path).call();
277 		FileUtils.delete(added);
278 		assertFalse(added.exists());
279 
280 		RevCommit stashed = git.stashCreate().call();
281 		assertNotNull(stashed);
282 		assertFalse(added.exists());
283 
284 		ObjectId unstashed = git.stashApply().call();
285 		assertEquals(stashed, unstashed);
286 		assertEquals("content2", read(added));
287 
288 		Status status = git.status().call();
289 		assertTrue(status.getChanged().isEmpty());
290 		assertTrue(status.getConflicting().isEmpty());
291 		assertTrue(status.getMissing().isEmpty());
292 		assertTrue(status.getModified().isEmpty());
293 		assertTrue(status.getRemoved().isEmpty());
294 		assertTrue(status.getUntracked().isEmpty());
295 
296 		assertEquals(1, status.getAdded().size());
297 		assertTrue(status.getAdded().contains(path));
298 	}
299 
300 	@Test
301 	public void workingDirectoryDeleteIndexEdit() throws Exception {
302 		writeTrashFile(PATH, "content2");
303 		git.add().addFilepattern(PATH).call();
304 		FileUtils.delete(committedFile);
305 		assertFalse(committedFile.exists());
306 
307 		RevCommit stashed = git.stashCreate().call();
308 		assertNotNull(stashed);
309 		assertEquals("content", read(committedFile));
310 
311 		ObjectId unstashed = git.stashApply().call();
312 		assertEquals(stashed, unstashed);
313 		assertFalse(committedFile.exists());
314 
315 		Status status = git.status().call();
316 		assertTrue(status.getAdded().isEmpty());
317 		assertEquals(1, status.getChanged().size());
318 		assertTrue(status.getChanged().contains(PATH));
319 		assertTrue(status.getConflicting().isEmpty());
320 		assertEquals(1, status.getMissing().size());
321 		assertTrue(status.getMissing().contains(PATH));
322 		assertTrue(status.getModified().isEmpty());
323 		assertTrue(status.getUntracked().isEmpty());
324 
325 		assertTrue(status.getRemoved().isEmpty());
326 	}
327 
328 	@Test
329 	public void multipleEdits() throws Exception {
330 		String addedPath = "file2.txt";
331 		git.rm().addFilepattern(PATH).call();
332 		File addedFile = writeTrashFile(addedPath, "content2");
333 		git.add().addFilepattern(addedPath).call();
334 
335 		RevCommit stashed = git.stashCreate().call();
336 		assertNotNull(stashed);
337 		assertTrue(committedFile.exists());
338 		assertFalse(addedFile.exists());
339 
340 		ObjectId unstashed = git.stashApply().call();
341 		assertEquals(stashed, unstashed);
342 
343 		Status status = git.status().call();
344 		assertTrue(status.getChanged().isEmpty());
345 		assertTrue(status.getConflicting().isEmpty());
346 		assertTrue(status.getMissing().isEmpty());
347 		assertTrue(status.getModified().isEmpty());
348 		assertTrue(status.getUntracked().isEmpty());
349 
350 		assertEquals(1, status.getRemoved().size());
351 		assertTrue(status.getRemoved().contains(PATH));
352 		assertEquals(1, status.getAdded().size());
353 		assertTrue(status.getAdded().contains(addedPath));
354 	}
355 
356 	@Test
357 	public void workingDirectoryContentConflict() throws Exception {
358 		writeTrashFile(PATH, "content2");
359 
360 		RevCommit stashed = git.stashCreate().call();
361 		assertNotNull(stashed);
362 		assertEquals("content", read(committedFile));
363 		assertTrue(git.status().call().isClean());
364 
365 		writeTrashFile(PATH, "content3");
366 
367 		try {
368 			git.stashApply().call();
369 			fail("Exception not thrown");
370 		} catch (StashApplyFailureException e) {
371 			// expected
372  		}
373 		assertEquals("content3", read(PATH));
374 	}
375 
376 	@Test
377 	public void stashedContentMerge() throws Exception {
378 		writeTrashFile(PATH, "content\nmore content\n");
379 		git.add().addFilepattern(PATH).call();
380 		git.commit().setMessage("more content").call();
381 
382 		writeTrashFile(PATH, "content\nhead change\nmore content\n");
383 		git.add().addFilepattern(PATH).call();
384 		git.commit().setMessage("even content").call();
385 
386 		writeTrashFile(PATH, "content\nstashed change\nmore content\n");
387 
388 		RevCommit stashed = git.stashCreate().call();
389 		assertNotNull(stashed);
390 		assertEquals("content\nhead change\nmore content\n",
391 				read(committedFile));
392 		assertTrue(git.status().call().isClean());
393 
394 		writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
395 		git.add().addFilepattern(PATH).call();
396 		git.commit().setMessage("committed change").call();
397 
398 		try {
399 			git.stashApply().call();
400 			fail("Expected conflict");
401 		} catch (StashApplyFailureException e) {
402 			// expected
403 		}
404 		Status status = new StatusCommand(db).call();
405 		assertEquals(1, status.getConflicting().size());
406 		assertEquals(
407 				"content\n<<<<<<< HEAD\n=======\nstashed change\n>>>>>>> stash\nmore content\ncommitted change\n",
408 				read(PATH));
409 	}
410 
411 	@Test
412 	public void stashedApplyOnOtherBranch() throws Exception {
413 		writeTrashFile(PATH, "content\nmore content\n");
414 		git.add().addFilepattern(PATH).call();
415 		git.commit().setMessage("more content").call();
416 		String path2 = "file2.txt";
417 		File file2 = writeTrashFile(path2, "content\nmore content\n");
418 		git.add().addFilepattern(PATH).call();
419 		git.add().addFilepattern(path2).call();
420 		git.commit().setMessage("even content").call();
421 
422 		String otherBranch = "otherBranch";
423 		git.branchCreate().setName(otherBranch).call();
424 
425 		writeTrashFile(PATH, "master content");
426 		git.add().addFilepattern(PATH).call();
427 		git.commit().setMessage("even content").call();
428 
429 		git.checkout().setName(otherBranch).call();
430 
431 		writeTrashFile(PATH, "otherBranch content");
432 		git.add().addFilepattern(PATH).call();
433 		git.commit().setMessage("even more content").call();
434 
435 		writeTrashFile(path2, "content\nstashed change\nmore content\n");
436 
437 		RevCommit stashed = git.stashCreate().call();
438 
439 		assertNotNull(stashed);
440 		assertEquals("content\nmore content\n", read(file2));
441 		assertEquals("otherBranch content",
442 				read(committedFile));
443 		assertTrue(git.status().call().isClean());
444 
445 		git.checkout().setName("master").call();
446 		git.stashApply().call();
447 		assertEquals("content\nstashed change\nmore content\n", read(file2));
448 		assertEquals("master content",
449 				read(committedFile));
450 	}
451 
452 	@Test
453 	public void stashedApplyOnOtherBranchWithStagedChange() throws Exception {
454 		writeTrashFile(PATH, "content\nmore content\n");
455 		git.add().addFilepattern(PATH).call();
456 		git.commit().setMessage("more content").call();
457 		String path2 = "file2.txt";
458 		File file2 = writeTrashFile(path2, "content\nmore content\n");
459 		git.add().addFilepattern(PATH).call();
460 		git.add().addFilepattern(path2).call();
461 		git.commit().setMessage("even content").call();
462 
463 		String otherBranch = "otherBranch";
464 		git.branchCreate().setName(otherBranch).call();
465 
466 		writeTrashFile(PATH, "master content");
467 		git.add().addFilepattern(PATH).call();
468 		git.commit().setMessage("even content").call();
469 
470 		git.checkout().setName(otherBranch).call();
471 
472 		writeTrashFile(PATH, "otherBranch content");
473 		git.add().addFilepattern(PATH).call();
474 		git.commit().setMessage("even more content").call();
475 
476 		writeTrashFile(path2,
477 				"content\nstashed change in index\nmore content\n");
478 		git.add().addFilepattern(path2).call();
479 		writeTrashFile(path2, "content\nstashed change\nmore content\n");
480 
481 		RevCommit stashed = git.stashCreate().call();
482 
483 		assertNotNull(stashed);
484 		assertEquals("content\nmore content\n", read(file2));
485 		assertEquals("otherBranch content", read(committedFile));
486 		assertTrue(git.status().call().isClean());
487 
488 		git.checkout().setName("master").call();
489 		git.stashApply().call();
490 		assertEquals("content\nstashed change\nmore content\n", read(file2));
491 		assertEquals(
492 				"[file.txt, mode:100644, content:master content]"
493 						+ "[file2.txt, mode:100644, content:content\nstashed change in index\nmore content\n]",
494 				indexState(CONTENT));
495 		assertEquals("master content", read(committedFile));
496 	}
497 
498 	@Test
499 	public void workingDirectoryContentMerge() 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\nstashed change\nmore content\n");
505 
506 		RevCommit stashed = git.stashCreate().call();
507 		assertNotNull(stashed);
508 		assertEquals("content\nmore content\n", read(committedFile));
509 		assertTrue(git.status().call().isClean());
510 
511 		writeTrashFile(PATH, "content\nmore content\ncommitted change\n");
512 		git.add().addFilepattern(PATH).call();
513 		git.commit().setMessage("committed change").call();
514 
515 		git.stashApply().call();
516 		assertEquals(
517 				"content\nstashed change\nmore content\ncommitted change\n",
518 				read(committedFile));
519 	}
520 
521 	@Test
522 	public void indexContentConflict() throws Exception {
523 		writeTrashFile(PATH, "content2");
524 
525 		RevCommit stashed = git.stashCreate().call();
526 		assertNotNull(stashed);
527 		assertEquals("content", read(committedFile));
528 		assertTrue(git.status().call().isClean());
529 
530 		writeTrashFile(PATH, "content3");
531 		git.add().addFilepattern(PATH).call();
532 		writeTrashFile(PATH, "content2");
533 
534 		try {
535 			git.stashApply().call();
536 			fail("Exception not thrown");
537 		} catch (StashApplyFailureException e) {
538 			// expected
539 		}
540 		assertEquals("content2", read(PATH));
541 	}
542 
543 	@Test
544 	public void workingDirectoryEditPreCommit() throws Exception {
545 		writeTrashFile(PATH, "content2");
546 
547 		RevCommit stashed = git.stashCreate().call();
548 		assertNotNull(stashed);
549 		assertEquals("content", read(committedFile));
550 		assertTrue(git.status().call().isClean());
551 
552 		String path2 = "file2.txt";
553 		writeTrashFile(path2, "content3");
554 		git.add().addFilepattern(path2).call();
555 		assertNotNull(git.commit().setMessage("adding file").call());
556 
557 		ObjectId unstashed = git.stashApply().call();
558 		assertEquals(stashed, unstashed);
559 
560 		Status status = git.status().call();
561 		assertTrue(status.getAdded().isEmpty());
562 		assertTrue(status.getChanged().isEmpty());
563 		assertTrue(status.getConflicting().isEmpty());
564 		assertTrue(status.getMissing().isEmpty());
565 		assertTrue(status.getRemoved().isEmpty());
566 		assertTrue(status.getUntracked().isEmpty());
567 
568 		assertEquals(1, status.getModified().size());
569 		assertTrue(status.getModified().contains(PATH));
570 	}
571 
572 	@Test
573 	public void stashChangeInANewSubdirectory() throws Exception {
574 		String subdir = "subdir";
575 		String fname = "file2.txt";
576 		String path = subdir + "/" + fname;
577 		String otherBranch = "otherbranch";
578 
579 		writeTrashFile(subdir, fname, "content2");
580 
581 		git.add().addFilepattern(path).call();
582 		RevCommit stashed = git.stashCreate().call();
583 		assertNotNull(stashed);
584 		assertTrue(git.status().call().isClean());
585 
586 		git.branchCreate().setName(otherBranch).call();
587 		git.checkout().setName(otherBranch).call();
588 
589 		ObjectId unstashed = git.stashApply().call();
590 		assertEquals(stashed, unstashed);
591 
592 		Status status = git.status().call();
593 		assertTrue(status.getChanged().isEmpty());
594 		assertTrue(status.getConflicting().isEmpty());
595 		assertTrue(status.getMissing().isEmpty());
596 		assertTrue(status.getRemoved().isEmpty());
597 		assertTrue(status.getModified().isEmpty());
598 		assertTrue(status.getUntracked().isEmpty());
599 
600 		assertEquals(1, status.getAdded().size());
601 		assertTrue(status.getAdded().contains(path));
602 	}
603 
604 	@Test
605 	public void unstashNonStashCommit() throws Exception {
606 		try {
607 			git.stashApply().setStashRef(head.name()).call();
608 			fail("Exception not thrown");
609 		} catch (JGitInternalException e) {
610 			assertEquals(MessageFormat.format(
611 					JGitText.get().stashCommitIncorrectNumberOfParents,
612 					head.name(), 0),
613 					e.getMessage());
614 		}
615 	}
616 
617 	@Test
618 	public void unstashNoHead() throws Exception {
619 		Repository repo = createWorkRepository();
620 		try {
621 			Git.wrap(repo).stashApply().call();
622 			fail("Exception not thrown");
623 		} catch (NoHeadException e) {
624 			assertNotNull(e.getMessage());
625 		}
626 	}
627 
628 	@Test
629 	public void noStashedCommits() throws Exception {
630 		try {
631 			git.stashApply().call();
632 			fail("Exception not thrown");
633 		} catch (InvalidRefNameException e) {
634 			assertNotNull(e.getMessage());
635 		}
636 	}
637 
638 	@Test
639 	public void testApplyStashWithDeletedFile() throws Exception {
640 		File file = writeTrashFile("file", "content");
641 		git.add().addFilepattern("file").call();
642 		git.commit().setMessage("x").call();
643 		file.delete();
644 		git.rm().addFilepattern("file").call();
645 		git.stashCreate().call();
646 		file.delete();
647 
648 		git.stashApply().setStashRef("stash@{0}").call();
649 
650 		assertFalse(file.exists());
651 	}
652 
653 	@Test
654 	public void untrackedFileNotIncluded() throws Exception {
655 		String untrackedPath = "untracked.txt";
656 		File untrackedFile = writeTrashFile(untrackedPath, "content");
657 		// at least one modification needed
658 		writeTrashFile(PATH, "content2");
659 		git.add().addFilepattern(PATH).call();
660 		git.stashCreate().call();
661 		assertTrue(untrackedFile.exists());
662 
663 		git.stashApply().setStashRef("stash@{0}").call();
664 		assertTrue(untrackedFile.exists());
665 
666 		Status status = git.status().call();
667 		assertEquals(1, status.getUntracked().size());
668 		assertTrue(status.getUntracked().contains(untrackedPath));
669 		assertEquals(1, status.getChanged().size());
670 		assertTrue(status.getChanged().contains(PATH));
671 		assertTrue(status.getAdded().isEmpty());
672 		assertTrue(status.getConflicting().isEmpty());
673 		assertTrue(status.getMissing().isEmpty());
674 		assertTrue(status.getRemoved().isEmpty());
675 		assertTrue(status.getModified().isEmpty());
676 	}
677 
678 	@Test
679 	public void untrackedFileIncluded() throws Exception {
680 		String path = "a/b/untracked.txt";
681 		File untrackedFile = writeTrashFile(path, "content");
682 		RevCommit stashedCommit = git.stashCreate().setIncludeUntracked(true)
683 				.call();
684 		assertNotNull(stashedCommit);
685 		assertFalse(untrackedFile.exists());
686 		deleteTrashFile("a/b"); // checkout should create parent dirs
687 
688 		git.stashApply().setStashRef("stash@{0}").call();
689 		assertTrue(untrackedFile.exists());
690 		assertEquals("content", read(path));
691 
692 		Status status = git.status().call();
693 		assertEquals(1, status.getUntracked().size());
694 		assertTrue(status.getAdded().isEmpty());
695 		assertTrue(status.getChanged().isEmpty());
696 		assertTrue(status.getConflicting().isEmpty());
697 		assertTrue(status.getMissing().isEmpty());
698 		assertTrue(status.getRemoved().isEmpty());
699 		assertTrue(status.getModified().isEmpty());
700 		assertTrue(status.getUntracked().contains(path));
701 	}
702 
703 	@Test
704 	public void untrackedFileConflictsWithCommit() throws Exception {
705 		String path = "untracked.txt";
706 		writeTrashFile(path, "untracked");
707 		git.stashCreate().setIncludeUntracked(true).call();
708 
709 		writeTrashFile(path, "committed");
710 		head = git.commit().setMessage("add file").call();
711 		git.add().addFilepattern(path).call();
712 		git.commit().setMessage("conflicting commit").call();
713 
714 		try {
715 			git.stashApply().setStashRef("stash@{0}").call();
716 			fail("StashApplyFailureException should be thrown.");
717 		} catch (StashApplyFailureException e) {
718 			assertEquals(e.getMessage(), JGitText.get().stashApplyConflict);
719 		}
720 		assertEquals("committed", read(path));
721 	}
722 
723 	@Test
724 	public void untrackedFileConflictsWithWorkingDirectory()
725 			throws Exception {
726 		String path = "untracked.txt";
727 		writeTrashFile(path, "untracked");
728 		git.stashCreate().setIncludeUntracked(true).call();
729 
730 		writeTrashFile(path, "working-directory");
731 		try {
732 			git.stashApply().setStashRef("stash@{0}").call();
733 			fail("StashApplyFailureException should be thrown.");
734 		} catch (StashApplyFailureException e) {
735 			assertEquals(e.getMessage(), JGitText.get().stashApplyConflict);
736 		}
737 		assertEquals("working-directory", read(path));
738 	}
739 }