1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.merge;
44
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertTrue;
47
48 import java.io.File;
49 import java.io.FileInputStream;
50 import java.io.IOException;
51
52 import org.eclipse.jgit.api.Git;
53 import org.eclipse.jgit.api.MergeResult;
54 import org.eclipse.jgit.api.MergeResult.MergeStatus;
55 import org.eclipse.jgit.api.errors.CheckoutConflictException;
56 import org.eclipse.jgit.api.errors.GitAPIException;
57 import org.eclipse.jgit.api.errors.JGitInternalException;
58 import org.eclipse.jgit.dircache.DirCache;
59 import org.eclipse.jgit.errors.NoMergeBaseException;
60 import org.eclipse.jgit.errors.NoMergeBaseException.MergeBaseFailureReason;
61 import org.eclipse.jgit.junit.RepositoryTestCase;
62 import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
63 import org.eclipse.jgit.revwalk.RevCommit;
64 import org.eclipse.jgit.treewalk.FileTreeIterator;
65 import org.eclipse.jgit.util.FileUtils;
66 import org.junit.Assert;
67 import org.junit.experimental.theories.DataPoint;
68 import org.junit.experimental.theories.Theories;
69 import org.junit.experimental.theories.Theory;
70 import org.junit.runner.RunWith;
71
72 @RunWith(Theories.class)
73 public class ResolveMergerTest extends RepositoryTestCase {
74
75 @DataPoint
76 public static MergeStrategy resolve = MergeStrategy.RESOLVE;
77
78 @DataPoint
79 public static MergeStrategy recursive = MergeStrategy.RECURSIVE;
80
81 @Theory
82 public void failingDeleteOfDirectoryWithUntrackedContent(
83 MergeStrategy strategy) throws Exception {
84 File folder1 = new File(db.getWorkTree(), "folder1");
85 FileUtils.mkdir(folder1);
86 File file = new File(folder1, "file1.txt");
87 write(file, "folder1--file1.txt");
88 file = new File(folder1, "file2.txt");
89 write(file, "folder1--file2.txt");
90
91 try (Git git = new Git(db)) {
92 git.add().addFilepattern(folder1.getName()).call();
93 RevCommit base = git.commit().setMessage("adding folder").call();
94
95 recursiveDelete(folder1);
96 git.rm().addFilepattern("folder1/file1.txt")
97 .addFilepattern("folder1/file2.txt").call();
98 RevCommit other = git.commit()
99 .setMessage("removing folders on 'other'").call();
100
101 git.checkout().setName(base.name()).call();
102
103 file = new File(db.getWorkTree(), "unrelated.txt");
104 write(file, "unrelated");
105
106 git.add().addFilepattern("unrelated.txt").call();
107 RevCommit head = git.commit().setMessage("Adding another file").call();
108
109
110
111 file = new File(folder1, "file3.txt");
112 write(file, "folder1--file3.txt");
113
114 ResolveMerger merger = (ResolveMerger) strategy.newMerger(db, false);
115 merger.setCommitNames(new String[] { "BASE", "HEAD", "other" });
116 merger.setWorkingTreeIterator(new FileTreeIterator(db));
117 boolean ok = merger.merge(head.getId(), other.getId());
118 assertTrue(ok);
119 assertTrue(file.exists());
120 }
121 }
122
123
124
125
126
127
128
129
130 @Theory
131 public void checkMergeConflictingTreesWithoutIndex(MergeStrategy strategy)
132 throws Exception {
133 Git git = Git.wrap(db);
134
135 writeTrashFile("d/1", "orig");
136 git.add().addFilepattern("d/1").call();
137 RevCommit first = git.commit().setMessage("added d/1").call();
138
139 writeTrashFile("d/1", "master");
140 RevCommit masterCommit = git.commit().setAll(true)
141 .setMessage("modified d/1 on master").call();
142
143 git.checkout().setCreateBranch(true).setStartPoint(first)
144 .setName("side").call();
145 writeTrashFile("d/1", "side");
146 git.commit().setAll(true).setMessage("modified d/1 on side").call();
147
148 git.rm().addFilepattern("d/1").call();
149 git.rm().addFilepattern("d").call();
150 MergeResult mergeRes = git.merge().setStrategy(strategy)
151 .include(masterCommit).call();
152 assertEquals(MergeStatus.CONFLICTING, mergeRes.getMergeStatus());
153 assertEquals(
154 "[d/1, mode:100644, stage:1, content:orig][d/1, mode:100644, stage:2, content:side][d/1, mode:100644, stage:3, content:master]",
155 indexState(CONTENT));
156 }
157
158
159
160
161
162
163
164
165 @Theory
166 public void checkMergeMergeableTreesWithoutIndex(MergeStrategy strategy)
167 throws Exception {
168 Git git = Git.wrap(db);
169
170 writeTrashFile("d/1", "1\n2\n3");
171 git.add().addFilepattern("d/1").call();
172 RevCommit first = git.commit().setMessage("added d/1").call();
173
174 writeTrashFile("d/1", "1master\n2\n3");
175 RevCommit masterCommit = git.commit().setAll(true)
176 .setMessage("modified d/1 on master").call();
177
178 git.checkout().setCreateBranch(true).setStartPoint(first)
179 .setName("side").call();
180 writeTrashFile("d/1", "1\n2\n3side");
181 git.commit().setAll(true).setMessage("modified d/1 on side").call();
182
183 git.rm().addFilepattern("d/1").call();
184 git.rm().addFilepattern("d").call();
185 MergeResult mergeRes = git.merge().setStrategy(strategy)
186 .include(masterCommit).call();
187 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
188 assertEquals("[d/1, mode:100644, content:1master\n2\n3side]",
189 indexState(CONTENT));
190 }
191
192
193
194
195
196
197
198
199 @Theory
200 public void checkUntrackedFolderIsNotAConflict(
201 MergeStrategy strategy) throws Exception {
202 Git git = Git.wrap(db);
203
204 writeTrashFile("d/1", "1");
205 git.add().addFilepattern("d/1").call();
206 RevCommit first = git.commit().setMessage("added d/1").call();
207
208 writeTrashFile("e/1", "4");
209 git.add().addFilepattern("e/1").call();
210 RevCommit masterCommit = git.commit().setMessage("added e/1").call();
211
212 git.checkout().setCreateBranch(true).setStartPoint(first)
213 .setName("side").call();
214 writeTrashFile("f/1", "5");
215 git.add().addFilepattern("f/1").call();
216 git.commit().setAll(true).setMessage("added f/1")
217 .call();
218
219
220 writeTrashFile("e/2", "d two");
221
222 MergeResult mergeRes = git.merge().setStrategy(strategy)
223 .include(masterCommit).call();
224 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
225 assertEquals(
226 "[d/1, mode:100644, content:1][e/1, mode:100644, content:4][f/1, mode:100644, content:5]",
227 indexState(CONTENT));
228 }
229
230
231
232
233
234
235
236 @Theory
237 public void checkFileReplacedByFolderInTheirs(MergeStrategy strategy)
238 throws Exception {
239 Git git = Git.wrap(db);
240
241 writeTrashFile("sub", "file");
242 git.add().addFilepattern("sub").call();
243 RevCommit first = git.commit().setMessage("initial").call();
244
245 git.checkout().setCreateBranch(true).setStartPoint(first)
246 .setName("side").call();
247
248 git.rm().addFilepattern("sub").call();
249 writeTrashFile("sub/file", "subfile");
250 git.add().addFilepattern("sub/file").call();
251 RevCommit masterCommit = git.commit().setMessage("file -> folder")
252 .call();
253
254 git.checkout().setName("master").call();
255 writeTrashFile("noop", "other");
256 git.add().addFilepattern("noop").call();
257 git.commit().setAll(true).setMessage("noop").call();
258
259 MergeResult mergeRes = git.merge().setStrategy(strategy)
260 .include(masterCommit).call();
261 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
262 assertEquals(
263 "[noop, mode:100644, content:other][sub/file, mode:100644, content:subfile]",
264 indexState(CONTENT));
265 }
266
267
268
269
270
271
272
273 @Theory
274 public void checkFileReplacedByFolderInOurs(MergeStrategy strategy)
275 throws Exception {
276 Git git = Git.wrap(db);
277
278 writeTrashFile("sub", "file");
279 git.add().addFilepattern("sub").call();
280 RevCommit first = git.commit().setMessage("initial").call();
281
282 git.checkout().setCreateBranch(true).setStartPoint(first)
283 .setName("side").call();
284 writeTrashFile("noop", "other");
285 git.add().addFilepattern("noop").call();
286 RevCommit sideCommit = git.commit().setAll(true).setMessage("noop")
287 .call();
288
289 git.checkout().setName("master").call();
290 git.rm().addFilepattern("sub").call();
291 writeTrashFile("sub/file", "subfile");
292 git.add().addFilepattern("sub/file").call();
293 git.commit().setMessage("file -> folder")
294 .call();
295
296 MergeResult mergeRes = git.merge().setStrategy(strategy)
297 .include(sideCommit).call();
298 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
299 assertEquals(
300 "[noop, mode:100644, content:other][sub/file, mode:100644, content:subfile]",
301 indexState(CONTENT));
302 }
303
304
305
306
307
308
309
310
311 @Theory
312 public void checkUntrackedEmpytFolderIsNotAConflictWithFile(
313 MergeStrategy strategy)
314 throws Exception {
315 Git git = Git.wrap(db);
316
317 writeTrashFile("d/1", "1");
318 git.add().addFilepattern("d/1").call();
319 RevCommit first = git.commit().setMessage("added d/1").call();
320
321 writeTrashFile("e", "4");
322 git.add().addFilepattern("e").call();
323 RevCommit masterCommit = git.commit().setMessage("added e").call();
324
325 git.checkout().setCreateBranch(true).setStartPoint(first)
326 .setName("side").call();
327 writeTrashFile("f/1", "5");
328 git.add().addFilepattern("f/1").call();
329 git.commit().setAll(true).setMessage("added f/1").call();
330
331
332
333 FileUtils.mkdirs(new File(trash, "e/1"), true);
334
335 MergeResult mergeRes = git.merge().setStrategy(strategy)
336 .include(masterCommit).call();
337 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
338 assertEquals(
339 "[d/1, mode:100644, content:1][e, mode:100644, content:4][f/1, mode:100644, content:5]",
340 indexState(CONTENT));
341 }
342
343 @Theory
344 public void mergeWithCrlfInWT(MergeStrategy strategy) throws IOException,
345 GitAPIException {
346 Git git = Git.wrap(db);
347 db.getConfig().setString("core", null, "autocrlf", "false");
348 db.getConfig().save();
349 writeTrashFile("crlf.txt", "some\r\ndata\r\n");
350 git.add().addFilepattern("crlf.txt").call();
351 git.commit().setMessage("base").call();
352
353 git.branchCreate().setName("brancha").call();
354
355 writeTrashFile("crlf.txt", "some\r\nmore\r\ndata\r\n");
356 git.add().addFilepattern("crlf.txt").call();
357 git.commit().setMessage("on master").call();
358
359 git.checkout().setName("brancha").call();
360 writeTrashFile("crlf.txt", "some\r\ndata\r\ntoo\r\n");
361 git.add().addFilepattern("crlf.txt").call();
362 git.commit().setMessage("on brancha").call();
363
364 db.getConfig().setString("core", null, "autocrlf", "input");
365 db.getConfig().save();
366
367 MergeResult mergeResult = git.merge().setStrategy(strategy)
368 .include(db.resolve("master"))
369 .call();
370 assertEquals(MergeResult.MergeStatus.MERGED,
371 mergeResult.getMergeStatus());
372 }
373
374
375
376
377
378
379
380
381 @Theory
382 public void checkMergeEqualTreesWithoutIndex(MergeStrategy strategy)
383 throws Exception {
384 Git git = Git.wrap(db);
385
386 writeTrashFile("d/1", "orig");
387 git.add().addFilepattern("d/1").call();
388 RevCommit first = git.commit().setMessage("added d/1").call();
389
390 writeTrashFile("d/1", "modified");
391 RevCommit masterCommit = git.commit().setAll(true)
392 .setMessage("modified d/1 on master").call();
393
394 git.checkout().setCreateBranch(true).setStartPoint(first)
395 .setName("side").call();
396 writeTrashFile("d/1", "modified");
397 git.commit().setAll(true).setMessage("modified d/1 on side").call();
398
399 git.rm().addFilepattern("d/1").call();
400 git.rm().addFilepattern("d").call();
401 MergeResult mergeRes = git.merge().setStrategy(strategy)
402 .include(masterCommit).call();
403 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
404 assertEquals("[d/1, mode:100644, content:modified]",
405 indexState(CONTENT));
406 }
407
408
409
410
411
412
413
414
415 @Theory
416 public void checkMergeEqualTreesInCore(MergeStrategy strategy)
417 throws Exception {
418 Git git = Git.wrap(db);
419
420 writeTrashFile("d/1", "orig");
421 git.add().addFilepattern("d/1").call();
422 RevCommit first = git.commit().setMessage("added d/1").call();
423
424 writeTrashFile("d/1", "modified");
425 RevCommit masterCommit = git.commit().setAll(true)
426 .setMessage("modified d/1 on master").call();
427
428 git.checkout().setCreateBranch(true).setStartPoint(first)
429 .setName("side").call();
430 writeTrashFile("d/1", "modified");
431 RevCommit sideCommit = git.commit().setAll(true)
432 .setMessage("modified d/1 on side").call();
433
434 git.rm().addFilepattern("d/1").call();
435 git.rm().addFilepattern("d").call();
436
437 ThreeWayMerger resolveMerger = (ThreeWayMerger) strategy.newMerger(db,
438 true);
439 boolean noProblems = resolveMerger.merge(masterCommit, sideCommit);
440 assertTrue(noProblems);
441 }
442
443
444
445
446
447
448
449
450 @Theory
451 public void checkMergeEqualNewTrees(MergeStrategy strategy)
452 throws Exception {
453 Git git = Git.wrap(db);
454
455 writeTrashFile("2", "orig");
456 git.add().addFilepattern("2").call();
457 RevCommit first = git.commit().setMessage("added 2").call();
458
459 writeTrashFile("d/1", "orig");
460 git.add().addFilepattern("d/1").call();
461 RevCommit masterCommit = git.commit().setAll(true)
462 .setMessage("added d/1 on master").call();
463
464 git.checkout().setCreateBranch(true).setStartPoint(first)
465 .setName("side").call();
466 writeTrashFile("d/1", "orig");
467 git.add().addFilepattern("d/1").call();
468 git.commit().setAll(true).setMessage("added d/1 on side").call();
469
470 git.rm().addFilepattern("d/1").call();
471 git.rm().addFilepattern("d").call();
472 MergeResult mergeRes = git.merge().setStrategy(strategy)
473 .include(masterCommit).call();
474 assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus());
475 assertEquals(
476 "[2, mode:100644, content:orig][d/1, mode:100644, content:orig]",
477 indexState(CONTENT));
478 }
479
480
481
482
483
484
485
486
487 @Theory
488 public void checkMergeConflictingNewTrees(MergeStrategy strategy)
489 throws Exception {
490 Git git = Git.wrap(db);
491
492 writeTrashFile("2", "orig");
493 git.add().addFilepattern("2").call();
494 RevCommit first = git.commit().setMessage("added 2").call();
495
496 writeTrashFile("d/1", "master");
497 git.add().addFilepattern("d/1").call();
498 RevCommit masterCommit = git.commit().setAll(true)
499 .setMessage("added d/1 on master").call();
500
501 git.checkout().setCreateBranch(true).setStartPoint(first)
502 .setName("side").call();
503 writeTrashFile("d/1", "side");
504 git.add().addFilepattern("d/1").call();
505 git.commit().setAll(true).setMessage("added d/1 on side").call();
506
507 git.rm().addFilepattern("d/1").call();
508 git.rm().addFilepattern("d").call();
509 MergeResult mergeRes = git.merge().setStrategy(strategy)
510 .include(masterCommit).call();
511 assertEquals(MergeStatus.CONFLICTING, mergeRes.getMergeStatus());
512 assertEquals(
513 "[2, mode:100644, content:orig][d/1, mode:100644, stage:2, content:side][d/1, mode:100644, stage:3, content:master]",
514 indexState(CONTENT));
515 }
516
517
518
519
520
521
522
523
524 @Theory
525 public void checkMergeConflictingFilesWithTreeInIndex(MergeStrategy strategy)
526 throws Exception {
527 Git git = Git.wrap(db);
528
529 writeTrashFile("0", "orig");
530 git.add().addFilepattern("0").call();
531 RevCommit first = git.commit().setMessage("added 0").call();
532
533 writeTrashFile("0", "master");
534 RevCommit masterCommit = git.commit().setAll(true)
535 .setMessage("modified 0 on master").call();
536
537 git.checkout().setCreateBranch(true).setStartPoint(first)
538 .setName("side").call();
539 writeTrashFile("0", "side");
540 git.commit().setAll(true).setMessage("modified 0 on side").call();
541
542 git.rm().addFilepattern("0").call();
543 writeTrashFile("0/0", "side");
544 git.add().addFilepattern("0/0").call();
545 MergeResult mergeRes = git.merge().setStrategy(strategy)
546 .include(masterCommit).call();
547 assertEquals(MergeStatus.FAILED, mergeRes.getMergeStatus());
548 }
549
550
551
552
553
554
555
556
557 @Theory
558 public void checkMergeMergeableFilesWithTreeInIndex(MergeStrategy strategy)
559 throws Exception {
560 Git git = Git.wrap(db);
561
562 writeTrashFile("0", "orig");
563 writeTrashFile("1", "1\n2\n3");
564 git.add().addFilepattern("0").addFilepattern("1").call();
565 RevCommit first = git.commit().setMessage("added 0, 1").call();
566
567 writeTrashFile("1", "1master\n2\n3");
568 RevCommit masterCommit = git.commit().setAll(true)
569 .setMessage("modified 1 on master").call();
570
571 git.checkout().setCreateBranch(true).setStartPoint(first)
572 .setName("side").call();
573 writeTrashFile("1", "1\n2\n3side");
574 git.commit().setAll(true).setMessage("modified 1 on side").call();
575
576 git.rm().addFilepattern("0").call();
577 writeTrashFile("0/0", "modified");
578 git.add().addFilepattern("0/0").call();
579 try {
580 git.merge().setStrategy(strategy).include(masterCommit).call();
581 Assert.fail("Didn't get the expected exception");
582 } catch (CheckoutConflictException e) {
583 assertEquals(1, e.getConflictingPaths().size());
584 assertEquals("0/0", e.getConflictingPaths().get(0));
585 }
586 }
587
588
589
590
591
592
593
594
595 @Theory
596 public void checkMergeCrissCross(MergeStrategy strategy) throws Exception {
597 Git git = Git.wrap(db);
598
599 writeTrashFile("1", "1\n2\n3");
600 git.add().addFilepattern("1").call();
601 RevCommit first = git.commit().setMessage("added 1").call();
602
603 writeTrashFile("1", "1master\n2\n3");
604 RevCommit masterCommit = git.commit().setAll(true)
605 .setMessage("modified 1 on master").call();
606
607 writeTrashFile("1", "1master2\n2\n3");
608 git.commit().setAll(true)
609 .setMessage("modified 1 on master again").call();
610
611 git.checkout().setCreateBranch(true).setStartPoint(first)
612 .setName("side").call();
613 writeTrashFile("1", "1\n2\na\nb\nc\n3side");
614 RevCommit sideCommit = git.commit().setAll(true)
615 .setMessage("modified 1 on side").call();
616
617 writeTrashFile("1", "1\n2\n3side2");
618 git.commit().setAll(true)
619 .setMessage("modified 1 on side again").call();
620
621 MergeResult result = git.merge().setStrategy(strategy)
622 .include(masterCommit).call();
623 assertEquals(MergeStatus.MERGED, result.getMergeStatus());
624 result.getNewHead();
625 git.checkout().setName("master").call();
626 result = git.merge().setStrategy(strategy).include(sideCommit).call();
627 assertEquals(MergeStatus.MERGED, result.getMergeStatus());
628
629
630
631
632 try {
633 MergeResult mergeResult = git.merge().setStrategy(strategy)
634 .include(git.getRepository().exactRef("refs/heads/side"))
635 .call();
636 assertEquals(MergeStrategy.RECURSIVE, strategy);
637 assertEquals(MergeResult.MergeStatus.MERGED,
638 mergeResult.getMergeStatus());
639 assertEquals("1master2\n2\n3side2", read("1"));
640 } catch (JGitInternalException e) {
641 assertEquals(MergeStrategy.RESOLVE, strategy);
642 assertTrue(e.getCause() instanceof NoMergeBaseException);
643 assertEquals(((NoMergeBaseException) e.getCause()).getReason(),
644 MergeBaseFailureReason.MULTIPLE_MERGE_BASES_NOT_SUPPORTED);
645 }
646 }
647
648 @Theory
649 public void checkLockedFilesToBeDeleted(MergeStrategy strategy)
650 throws Exception {
651 Git git = Git.wrap(db);
652
653 writeTrashFile("a.txt", "orig");
654 writeTrashFile("b.txt", "orig");
655 git.add().addFilepattern("a.txt").addFilepattern("b.txt").call();
656 RevCommit first = git.commit().setMessage("added a.txt, b.txt").call();
657
658
659 writeTrashFile("a.txt", "master");
660 git.rm().addFilepattern("b.txt").call();
661 RevCommit masterCommit = git.commit()
662 .setMessage("modified a.txt, deleted b.txt").setAll(true)
663 .call();
664
665
666 git.checkout().setCreateBranch(true).setStartPoint(first)
667 .setName("side").call();
668 writeTrashFile("c.txt", "side");
669 git.add().addFilepattern("c.txt").call();
670 git.commit().setMessage("added c.txt").call();
671
672
673 FileInputStream fis = new FileInputStream(new File(db.getWorkTree(),
674 "b.txt"));
675 MergeResult mergeRes = git.merge().setStrategy(strategy)
676 .include(masterCommit).call();
677 if (mergeRes.getMergeStatus().equals(MergeStatus.FAILED)) {
678
679 assertEquals(1, mergeRes.getFailingPaths().size());
680 assertEquals(MergeFailureReason.COULD_NOT_DELETE, mergeRes
681 .getFailingPaths().get("b.txt"));
682 }
683 assertEquals("[a.txt, mode:100644, content:master]"
684 + "[c.txt, mode:100644, content:side]", indexState(CONTENT));
685 fis.close();
686 }
687
688 @Theory
689 public void checkForCorrectIndex(MergeStrategy strategy) throws Exception {
690 File f;
691 long lastTs4, lastTsIndex;
692 Git git = Git.wrap(db);
693 File indexFile = db.getIndexFile();
694
695
696 f = writeTrashFiles(false, "orig", "orig", "1\n2\n3", "orig", "orig");
697 lastTs4 = f.lastModified();
698
699
700
701
702
703 fsTick(f);
704 git.add().addFilepattern(".").call();
705 RevCommit firstCommit = git.commit().setMessage("initial commit")
706 .call();
707 checkConsistentLastModified("0", "1", "2", "3", "4");
708 checkModificationTimeStampOrder("1", "2", "3", "4", "<.git/index");
709 assertEquals("Commit should not touch working tree file 4", lastTs4,
710 new File(db.getWorkTree(), "4").lastModified());
711 lastTsIndex = indexFile.lastModified();
712
713
714
715 fsTick(indexFile);
716 f = writeTrashFiles(false, "master", null, "1master\n2\n3", "master",
717 null);
718 fsTick(f);
719 git.add().addFilepattern(".").call();
720 RevCommit masterCommit = git.commit().setMessage("master commit")
721 .call();
722 checkConsistentLastModified("0", "1", "2", "3", "4");
723 checkModificationTimeStampOrder("1", "4", "*" + lastTs4, "<*"
724 + lastTsIndex, "<0", "2", "3", "<.git/index");
725 lastTsIndex = indexFile.lastModified();
726
727
728 fsTick(indexFile);
729 git.checkout().setCreateBranch(true).setStartPoint(firstCommit)
730 .setName("side").call();
731 checkConsistentLastModified("0", "1", "2", "3", "4");
732 checkModificationTimeStampOrder("1", "4", "*" + lastTs4, "<*"
733 + lastTsIndex, "<0", "2", "3", ".git/index");
734 lastTsIndex = indexFile.lastModified();
735
736
737
738
739 assertEquals("[0, mode:100644, content:orig]"
740 + "[1, mode:100644, content:orig]"
741 + "[2, mode:100644, content:1\n2\n3]"
742 + "[3, mode:100644, content:orig]"
743 + "[4, mode:100644, content:orig]",
744 indexState(CONTENT));
745 fsTick(indexFile);
746 f = writeTrashFiles(false, "orig", "orig", "1\n2\n3", "orig", "orig");
747 lastTs4 = f.lastModified();
748 fsTick(f);
749 git.add().addFilepattern(".").call();
750 checkConsistentLastModified("0", "1", "2", "3", "4");
751 checkModificationTimeStampOrder("*" + lastTsIndex, "<0", "1", "2", "3",
752 "4", "<.git/index");
753 lastTsIndex = indexFile.lastModified();
754
755
756 fsTick(indexFile);
757 f = writeTrashFiles(false, null, "side", "1\n2\n3side", "side", null);
758 fsTick(f);
759 git.add().addFilepattern(".").call();
760 git.commit().setMessage("side commit").call();
761 checkConsistentLastModified("0", "1", "2", "3", "4");
762 checkModificationTimeStampOrder("0", "4", "*" + lastTs4, "<*"
763 + lastTsIndex, "<1", "2", "3", "<.git/index");
764 lastTsIndex = indexFile.lastModified();
765
766
767 fsTick(indexFile);
768 git.merge().setStrategy(strategy).include(masterCommit).call();
769 checkConsistentLastModified("0", "1", "2", "4");
770 checkModificationTimeStampOrder("4", "*" + lastTs4, "<1", "<*"
771 + lastTsIndex, "<0", "2", "3", ".git/index");
772 assertEquals(
773 "[0, mode:100644, content:master]"
774 + "[1, mode:100644, content:side]"
775 + "[2, mode:100644, content:1master\n2\n3side]"
776 + "[3, mode:100644, stage:1, content:orig][3, mode:100644, stage:2, content:side][3, mode:100644, stage:3, content:master]"
777 + "[4, mode:100644, content:orig]",
778 indexState(CONTENT));
779 }
780
781
782
783 private void checkConsistentLastModified(String... pathes)
784 throws IOException {
785 DirCache dc = db.readDirCache();
786 File workTree = db.getWorkTree();
787 for (String path : pathes)
788 assertEquals(
789 "IndexEntry with path "
790 + path
791 + " has lastmodified with is different from the worktree file",
792 new File(workTree, path).lastModified(), dc.getEntry(path)
793 .getLastModified());
794 }
795
796
797
798
799
800
801
802 private void checkModificationTimeStampOrder(String... pathes) {
803 long lastMod = Long.MIN_VALUE;
804 for (String p : pathes) {
805 boolean strong = p.startsWith("<");
806 boolean fixed = p.charAt(strong ? 1 : 0) == '*';
807 p = p.substring((strong ? 1 : 0) + (fixed ? 1 : 0));
808 long curMod = fixed ? Long.valueOf(p).longValue() : new File(
809 db.getWorkTree(), p).lastModified();
810 if (strong)
811 assertTrue("path " + p + " is not younger than predecesssor",
812 curMod > lastMod);
813 else
814 assertTrue("path " + p + " is older than predecesssor",
815 curMod >= lastMod);
816 }
817 }
818 }