1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jgit.lib;
15
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.assertFalse;
18 import static org.junit.Assert.assertTrue;
19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.TreeSet;
27
28 import org.eclipse.jgit.api.Git;
29 import org.eclipse.jgit.api.MergeResult;
30 import org.eclipse.jgit.api.MergeResult.MergeStatus;
31 import org.eclipse.jgit.api.errors.GitAPIException;
32 import org.eclipse.jgit.dircache.DirCache;
33 import org.eclipse.jgit.dircache.DirCacheBuilder;
34 import org.eclipse.jgit.dircache.DirCacheEditor;
35 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
36 import org.eclipse.jgit.dircache.DirCacheEntry;
37 import org.eclipse.jgit.junit.RepositoryTestCase;
38 import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
39 import org.eclipse.jgit.lib.IndexDiff.StageState;
40 import org.eclipse.jgit.merge.MergeStrategy;
41 import org.eclipse.jgit.revwalk.RevCommit;
42 import org.eclipse.jgit.storage.file.FileBasedConfig;
43 import org.eclipse.jgit.treewalk.FileTreeIterator;
44 import org.eclipse.jgit.util.IO;
45 import org.junit.Test;
46
47 public class IndexDiffTest extends RepositoryTestCase {
48
49 static PathEdit add(final Repository db, final File workdir,
50 final String path) throws FileNotFoundException, IOException {
51 final File f = new File(workdir, path);
52 ObjectId id;
53 try (ObjectInserter inserter = db.newObjectInserter()) {
54 id = inserter.insert(Constants.OBJ_BLOB,
55 IO.readFully(f));
56 }
57 return new PathEdit(path) {
58 @Override
59 public void apply(DirCacheEntry ent) {
60 ent.setFileMode(FileMode.REGULAR_FILE);
61 ent.setLength(f.length());
62 ent.setObjectId(id);
63 }
64 };
65 }
66
67 @Test
68 public void testAdded() throws IOException {
69 writeTrashFile("file1", "file1");
70 writeTrashFile("dir/subfile", "dir/subfile");
71 ObjectId tree = insertTree(new TreeFormatter());
72
73 DirCache index = db.lockDirCache();
74 DirCacheEditor editor = index.editor();
75 editor.add(add(db, trash, "file1"));
76 editor.add(add(db, trash, "dir/subfile"));
77 editor.commit();
78 FileTreeIterator iterator = new FileTreeIterator(db);
79 IndexDiff diff = new IndexDiff(db, tree, iterator);
80 diff.diff();
81 assertEquals(2, diff.getAdded().size());
82 assertTrue(diff.getAdded().contains("file1"));
83 assertTrue(diff.getAdded().contains("dir/subfile"));
84 assertEquals(0, diff.getChanged().size());
85 assertEquals(0, diff.getModified().size());
86 assertEquals(0, diff.getRemoved().size());
87 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
88 }
89
90 @Test
91 public void testMissing() throws Exception {
92 File file2 = writeTrashFile("file2", "file2");
93 File file3 = writeTrashFile("dir/file3", "dir/file3");
94 try (Git git = new Git(db)) {
95 git.add().addFilepattern("file2").addFilepattern("dir/file3")
96 .call();
97 git.commit().setMessage("commit").call();
98 }
99 assertTrue(file2.delete());
100 assertTrue(file3.delete());
101 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
102 new FileTreeIterator(db));
103 diff.diff();
104 assertEquals(2, diff.getMissing().size());
105 assertTrue(diff.getMissing().contains("file2"));
106 assertTrue(diff.getMissing().contains("dir/file3"));
107 assertEquals(0, diff.getChanged().size());
108 assertEquals(0, diff.getModified().size());
109 assertEquals(0, diff.getAdded().size());
110 assertEquals(0, diff.getRemoved().size());
111 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
112 }
113
114 @Test
115 public void testRemoved() throws IOException {
116 writeTrashFile("file2", "file2");
117 writeTrashFile("dir/file3", "dir/file3");
118
119 TreeFormatter dir = new TreeFormatter();
120 dir.append("file3", FileMode.REGULAR_FILE, ObjectId.fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"));
121
122 TreeFormatter tree = new TreeFormatter();
123 tree.append("file2", FileMode.REGULAR_FILE, ObjectId.fromString("30d67d4672d5c05833b7192cc77a79eaafb5c7ad"));
124 tree.append("dir", FileMode.TREE, insertTree(dir));
125 ObjectId treeId = insertTree(tree);
126
127 FileTreeIterator iterator = new FileTreeIterator(db);
128 IndexDiff diff = new IndexDiff(db, treeId, iterator);
129 diff.diff();
130 assertEquals(2, diff.getRemoved().size());
131 assertTrue(diff.getRemoved().contains("file2"));
132 assertTrue(diff.getRemoved().contains("dir/file3"));
133 assertEquals(0, diff.getChanged().size());
134 assertEquals(0, diff.getModified().size());
135 assertEquals(0, diff.getAdded().size());
136 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
137 }
138
139 @Test
140 public void testModified() throws IOException, GitAPIException {
141
142 writeTrashFile("file2", "file2");
143 writeTrashFile("dir/file3", "dir/file3");
144
145 try (Git git = new Git(db)) {
146 git.add().addFilepattern("file2").addFilepattern("dir/file3").call();
147 }
148
149 writeTrashFile("dir/file3", "changed");
150
151 TreeFormatter dir = new TreeFormatter();
152 dir.append("file3", FileMode.REGULAR_FILE, ObjectId.fromString("0123456789012345678901234567890123456789"));
153
154 TreeFormatter tree = new TreeFormatter();
155 tree.append("dir", FileMode.TREE, insertTree(dir));
156 tree.append("file2", FileMode.REGULAR_FILE, ObjectId.fromString("0123456789012345678901234567890123456789"));
157 ObjectId treeId = insertTree(tree);
158
159 FileTreeIterator iterator = new FileTreeIterator(db);
160 IndexDiff diff = new IndexDiff(db, treeId, iterator);
161 diff.diff();
162 assertEquals(2, diff.getChanged().size());
163 assertTrue(diff.getChanged().contains("file2"));
164 assertTrue(diff.getChanged().contains("dir/file3"));
165 assertEquals(1, diff.getModified().size());
166 assertTrue(diff.getModified().contains("dir/file3"));
167 assertEquals(0, diff.getAdded().size());
168 assertEquals(0, diff.getRemoved().size());
169 assertEquals(0, diff.getMissing().size());
170 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
171 }
172
173 @Test
174 public void testConflicting() throws Exception {
175 try (Git git = new Git(db)) {
176 writeTrashFile("a", "1\na\n3\n");
177 writeTrashFile("b", "1\nb\n3\n");
178 git.add().addFilepattern("a").addFilepattern("b").call();
179 RevCommit initialCommit = git.commit().setMessage("initial").call();
180
181
182 createBranch(initialCommit, "refs/heads/side");
183 checkoutBranch("refs/heads/side");
184 writeTrashFile("a", "1\na(side)\n3\n");
185 writeTrashFile("b", "1\nb\n3\n(side)");
186 git.add().addFilepattern("a").addFilepattern("b").call();
187 RevCommit secondCommit = git.commit().setMessage("side").call();
188
189
190 checkoutBranch("refs/heads/master");
191 writeTrashFile("a", "1\na(main)\n3\n");
192 git.add().addFilepattern("a").call();
193 git.commit().setMessage("main").call();
194
195
196 MergeResult result = git.merge().include(secondCommit.getId())
197 .setStrategy(MergeStrategy.RESOLVE).call();
198 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
199 }
200
201 FileTreeIterator iterator = new FileTreeIterator(db);
202 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
203 diff.diff();
204
205 assertEquals("[b]",
206 new TreeSet<>(diff.getChanged()).toString());
207 assertEquals("[]", diff.getAdded().toString());
208 assertEquals("[]", diff.getRemoved().toString());
209 assertEquals("[]", diff.getMissing().toString());
210 assertEquals("[]", diff.getModified().toString());
211 assertEquals("[a]", diff.getConflicting().toString());
212 assertEquals(StageState.BOTH_MODIFIED,
213 diff.getConflictingStageStates().get("a"));
214 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
215 }
216
217 @Test
218 public void testConflictingDeletedAndModified() throws Exception {
219 try (Git git = new Git(db)) {
220 writeTrashFile("a", "1\na\n3\n");
221 writeTrashFile("b", "1\nb\n3\n");
222 git.add().addFilepattern("a").addFilepattern("b").call();
223 RevCommit initialCommit = git.commit().setMessage("initial").call();
224
225
226 createBranch(initialCommit, "refs/heads/side");
227 checkoutBranch("refs/heads/side");
228 git.rm().addFilepattern("a").call();
229 RevCommit secondCommit = git.commit().setMessage("side").call();
230
231
232 checkoutBranch("refs/heads/master");
233 writeTrashFile("a", "1\na(main)\n3\n");
234 git.add().addFilepattern("a").call();
235 git.commit().setMessage("main").call();
236
237
238 MergeResult result = git.merge().include(secondCommit.getId())
239 .setStrategy(MergeStrategy.RESOLVE).call();
240 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
241 }
242
243 FileTreeIterator iterator = new FileTreeIterator(db);
244 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
245 diff.diff();
246
247 assertEquals("[]", new TreeSet<>(diff.getChanged()).toString());
248 assertEquals("[]", diff.getAdded().toString());
249 assertEquals("[]", diff.getRemoved().toString());
250 assertEquals("[]", diff.getMissing().toString());
251 assertEquals("[]", diff.getModified().toString());
252 assertEquals("[a]", diff.getConflicting().toString());
253 assertEquals(StageState.DELETED_BY_THEM,
254 diff.getConflictingStageStates().get("a"));
255 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
256 }
257
258 @Test
259 public void testConflictingFromMultipleCreations() throws Exception {
260 try (Git git = new Git(db)) {
261 writeTrashFile("a", "1\na\n3\n");
262 git.add().addFilepattern("a").call();
263 RevCommit initialCommit = git.commit().setMessage("initial").call();
264
265 createBranch(initialCommit, "refs/heads/side");
266 checkoutBranch("refs/heads/side");
267
268 writeTrashFile("b", "1\nb(side)\n3\n");
269 git.add().addFilepattern("b").call();
270 RevCommit secondCommit = git.commit().setMessage("side").call();
271
272 checkoutBranch("refs/heads/master");
273
274 writeTrashFile("b", "1\nb(main)\n3\n");
275 git.add().addFilepattern("b").call();
276 git.commit().setMessage("main").call();
277
278 MergeResult result = git.merge().include(secondCommit.getId())
279 .setStrategy(MergeStrategy.RESOLVE).call();
280 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
281 }
282
283 FileTreeIterator iterator = new FileTreeIterator(db);
284 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
285 diff.diff();
286
287 assertEquals("[]", new TreeSet<>(diff.getChanged()).toString());
288 assertEquals("[]", diff.getAdded().toString());
289 assertEquals("[]", diff.getRemoved().toString());
290 assertEquals("[]", diff.getMissing().toString());
291 assertEquals("[]", diff.getModified().toString());
292 assertEquals("[b]", diff.getConflicting().toString());
293 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
294 }
295
296 @Test
297 public void testUnchangedSimple() throws IOException, GitAPIException {
298 writeTrashFile("a.b", "a.b");
299 writeTrashFile("a.c", "a.c");
300 writeTrashFile("a=c", "a=c");
301 writeTrashFile("a=d", "a=d");
302 try (Git git = new Git(db)) {
303 git.add().addFilepattern("a.b").call();
304 git.add().addFilepattern("a.c").call();
305 git.add().addFilepattern("a=c").call();
306 git.add().addFilepattern("a=d").call();
307 }
308
309 TreeFormatter tree = new TreeFormatter();
310
311 tree.append("a.b", FileMode.REGULAR_FILE, ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851"));
312 tree.append("a.c", FileMode.REGULAR_FILE, ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca"));
313 tree.append("a=c", FileMode.REGULAR_FILE, ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714"));
314 tree.append("a=d", FileMode.REGULAR_FILE, ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2"));
315 ObjectId treeId = insertTree(tree);
316
317 FileTreeIterator iterator = new FileTreeIterator(db);
318 IndexDiff diff = new IndexDiff(db, treeId, iterator);
319 diff.diff();
320 assertEquals(0, diff.getChanged().size());
321 assertEquals(0, diff.getAdded().size());
322 assertEquals(0, diff.getRemoved().size());
323 assertEquals(0, diff.getMissing().size());
324 assertEquals(0, diff.getModified().size());
325 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
326 }
327
328
329
330
331
332
333
334
335 @Test
336 public void testUnchangedComplex() throws IOException, GitAPIException {
337 writeTrashFile("a.b", "a.b");
338 writeTrashFile("a.c", "a.c");
339 writeTrashFile("a/b.b/b", "a/b.b/b");
340 writeTrashFile("a/b", "a/b");
341 writeTrashFile("a/c", "a/c");
342 writeTrashFile("a=c", "a=c");
343 writeTrashFile("a=d", "a=d");
344 try (Git git = new Git(db)) {
345 git.add().addFilepattern("a.b").addFilepattern("a.c")
346 .addFilepattern("a/b.b/b").addFilepattern("a/b")
347 .addFilepattern("a/c").addFilepattern("a=c")
348 .addFilepattern("a=d").call();
349 }
350
351
352
353 TreeFormatter bb = new TreeFormatter();
354 bb.append("b", FileMode.REGULAR_FILE, ObjectId.fromString("8d840bd4e2f3a48ff417c8e927d94996849933fd"));
355
356 TreeFormatter a = new TreeFormatter();
357 a.append("b", FileMode.REGULAR_FILE, ObjectId
358 .fromString("db89c972fc57862eae378f45b74aca228037d415"));
359 a.append("b.b", FileMode.TREE, insertTree(bb));
360 a.append("c", FileMode.REGULAR_FILE, ObjectId.fromString("52ad142a008aeb39694bafff8e8f1be75ed7f007"));
361
362 TreeFormatter tree = new TreeFormatter();
363 tree.append("a.b", FileMode.REGULAR_FILE, ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851"));
364 tree.append("a.c", FileMode.REGULAR_FILE, ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca"));
365 tree.append("a", FileMode.TREE, insertTree(a));
366 tree.append("a=c", FileMode.REGULAR_FILE, ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714"));
367 tree.append("a=d", FileMode.REGULAR_FILE, ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2"));
368 ObjectId treeId = insertTree(tree);
369
370 FileTreeIterator iterator = new FileTreeIterator(db);
371 IndexDiff diff = new IndexDiff(db, treeId, iterator);
372 diff.diff();
373 assertEquals(0, diff.getChanged().size());
374 assertEquals(0, diff.getAdded().size());
375 assertEquals(0, diff.getRemoved().size());
376 assertEquals(0, diff.getMissing().size());
377 assertEquals(0, diff.getModified().size());
378 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
379 }
380
381 private ObjectId insertTree(TreeFormatter tree) throws IOException {
382 try (ObjectInserter oi = db.newObjectInserter()) {
383 ObjectId id = oi.insert(tree);
384 oi.flush();
385 return id;
386 }
387 }
388
389
390
391
392
393
394
395 @Test
396 public void testRemovedUntracked() throws Exception{
397 String path = "file";
398 try (Git git = new Git(db)) {
399 writeTrashFile(path, "content");
400 git.add().addFilepattern(path).call();
401 git.commit().setMessage("commit").call();
402 }
403 removeFromIndex(path);
404 FileTreeIterator iterator = new FileTreeIterator(db);
405 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
406 diff.diff();
407 assertTrue(diff.getRemoved().contains(path));
408 assertTrue(diff.getUntracked().contains(path));
409 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
410 }
411
412
413
414
415
416 @Test
417 public void testUntrackedFolders() throws Exception {
418 try (Git git = new Git(db)) {
419 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
420 new FileTreeIterator(db));
421 diff.diff();
422 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
423
424 writeTrashFile("readme", "");
425 writeTrashFile("src/com/A.java", "");
426 writeTrashFile("src/com/B.java", "");
427 writeTrashFile("src/org/A.java", "");
428 writeTrashFile("src/org/B.java", "");
429 writeTrashFile("target/com/A.java", "");
430 writeTrashFile("target/com/B.java", "");
431 writeTrashFile("target/org/A.java", "");
432 writeTrashFile("target/org/B.java", "");
433
434 git.add().addFilepattern("src").addFilepattern("readme").call();
435 git.commit().setMessage("initial").call();
436
437 diff = new IndexDiff(db, Constants.HEAD,
438 new FileTreeIterator(db));
439 diff.diff();
440 assertEquals(new HashSet<>(Arrays.asList("target")),
441 diff.getUntrackedFolders());
442
443 writeTrashFile("src/tst/A.java", "");
444 writeTrashFile("src/tst/B.java", "");
445
446 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
447 diff.diff();
448 assertEquals(new HashSet<>(Arrays.asList("target", "src/tst")),
449 diff.getUntrackedFolders());
450
451 git.rm().addFilepattern("src/com/B.java").addFilepattern("src/org")
452 .call();
453 git.commit().setMessage("second").call();
454 writeTrashFile("src/org/C.java", "");
455
456 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
457 diff.diff();
458 assertEquals(
459 new HashSet<>(Arrays.asList("src/org", "src/tst",
460 "target")),
461 diff.getUntrackedFolders());
462 }
463 }
464
465
466
467
468
469
470
471 @Test
472 public void testUntrackedNotIgnoredFolders() throws Exception {
473 try (Git git = new Git(db)) {
474 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
475 new FileTreeIterator(db));
476 diff.diff();
477 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
478
479 writeTrashFile("readme", "");
480 writeTrashFile("sr/com/X.java", "");
481 writeTrashFile("src/com/A.java", "");
482 writeTrashFile("src/org/B.java", "");
483 writeTrashFile("srcs/org/Y.java", "");
484 writeTrashFile("target/com/A.java", "");
485 writeTrashFile("target/org/B.java", "");
486 writeTrashFile(".gitignore", "/target\n/sr");
487
488 git.add().addFilepattern("readme").addFilepattern(".gitignore")
489 .addFilepattern("srcs/").call();
490 git.commit().setMessage("initial").call();
491
492 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
493 diff.diff();
494 assertEquals(new HashSet<>(Arrays.asList("src")),
495 diff.getUntrackedFolders());
496 assertEquals(new HashSet<>(Arrays.asList("sr", "target")),
497 diff.getIgnoredNotInIndex());
498
499 git.add().addFilepattern("src").call();
500 writeTrashFile("sr/com/X1.java", "");
501 writeTrashFile("src/tst/A.java", "");
502 writeTrashFile("src/tst/B.java", "");
503 writeTrashFile("srcs/com/Y1.java", "");
504 deleteTrashFile(".gitignore");
505
506 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
507 diff.diff();
508 assertEquals(
509 new HashSet<>(Arrays.asList("srcs/com", "sr", "src/tst",
510 "target")),
511 diff.getUntrackedFolders());
512 }
513 }
514
515 @Test
516 public void testAssumeUnchanged() throws Exception {
517 try (Git git = new Git(db)) {
518 String path = "file";
519 writeTrashFile(path, "content");
520 git.add().addFilepattern(path).call();
521 String path2 = "file2";
522 writeTrashFile(path2, "content");
523 String path3 = "file3";
524 writeTrashFile(path3, "some content");
525 git.add().addFilepattern(path2).addFilepattern(path3).call();
526 git.commit().setMessage("commit").call();
527 assumeUnchanged(path2);
528 assumeUnchanged(path3);
529 writeTrashFile(path, "more content");
530 deleteTrashFile(path3);
531
532 FileTreeIterator iterator = new FileTreeIterator(db);
533 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
534 diff.diff();
535 assertEquals(2, diff.getAssumeUnchanged().size());
536 assertEquals(1, diff.getModified().size());
537 assertEquals(0, diff.getChanged().size());
538 assertTrue(diff.getAssumeUnchanged().contains("file2"));
539 assertTrue(diff.getAssumeUnchanged().contains("file3"));
540 assertTrue(diff.getModified().contains("file"));
541
542 git.add().addFilepattern(".").call();
543
544 iterator = new FileTreeIterator(db);
545 diff = new IndexDiff(db, Constants.HEAD, iterator);
546 diff.diff();
547 assertEquals(2, diff.getAssumeUnchanged().size());
548 assertEquals(0, diff.getModified().size());
549 assertEquals(1, diff.getChanged().size());
550 assertTrue(diff.getAssumeUnchanged().contains("file2"));
551 assertTrue(diff.getAssumeUnchanged().contains("file3"));
552 assertTrue(diff.getChanged().contains("file"));
553 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
554 }
555 }
556
557 @Test
558 public void testStageState() throws IOException {
559 final int base = DirCacheEntry.STAGE_1;
560 final int ours = DirCacheEntry.STAGE_2;
561 final int theirs = DirCacheEntry.STAGE_3;
562 verifyStageState(StageState.BOTH_DELETED, base);
563 verifyStageState(StageState.DELETED_BY_THEM, ours, base);
564 verifyStageState(StageState.DELETED_BY_US, base, theirs);
565 verifyStageState(StageState.BOTH_MODIFIED, base, ours, theirs);
566 verifyStageState(StageState.ADDED_BY_US, ours);
567 verifyStageState(StageState.BOTH_ADDED, ours, theirs);
568 verifyStageState(StageState.ADDED_BY_THEM, theirs);
569
570 assertTrue(StageState.BOTH_DELETED.hasBase());
571 assertFalse(StageState.BOTH_DELETED.hasOurs());
572 assertFalse(StageState.BOTH_DELETED.hasTheirs());
573 assertFalse(StageState.BOTH_ADDED.hasBase());
574 assertTrue(StageState.BOTH_ADDED.hasOurs());
575 assertTrue(StageState.BOTH_ADDED.hasTheirs());
576 }
577
578 @Test
579 public void testStageState_mergeAndReset_bug() throws Exception {
580 try (Git git = new Git(db)) {
581 writeTrashFile("a", "content");
582 git.add().addFilepattern("a").call();
583 RevCommit initialCommit = git.commit().setMessage("initial commit")
584 .call();
585
586
587 final String branchName = Constants.R_HEADS + "branch";
588 createBranch(initialCommit, branchName);
589 checkoutBranch(branchName);
590 writeTrashFile("b", "second file content - branch");
591 git.add().addFilepattern("b").call();
592 RevCommit branchCommit = git.commit().setMessage("branch commit")
593 .call();
594
595
596 checkoutBranch(Constants.R_HEADS + Constants.MASTER);
597 writeTrashFile("b", "second file content - master");
598 git.add().addFilepattern("b").call();
599 git.commit().setMessage("master commit").call();
600
601
602 MergeResult result = git.merge().include(branchCommit).call();
603 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
604
605 FileTreeIterator iterator = new FileTreeIterator(db);
606 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
607 diff.diff();
608
609 assertTrue(diff.getChanged().isEmpty());
610 assertTrue(diff.getAdded().isEmpty());
611 assertTrue(diff.getRemoved().isEmpty());
612 assertTrue(diff.getMissing().isEmpty());
613 assertTrue(diff.getModified().isEmpty());
614 assertEquals(1, diff.getConflicting().size());
615 assertTrue(diff.getConflicting().contains("b"));
616 assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
617 .get("b"));
618 assertTrue(diff.getUntrackedFolders().isEmpty());
619
620
621 writeTrashFile("b", "second file content - master");
622
623
624 iterator = new FileTreeIterator(db);
625 diff = new IndexDiff(db, Constants.HEAD, iterator);
626 diff.diff();
627
628 assertTrue(diff.getChanged().isEmpty());
629 assertTrue(diff.getAdded().isEmpty());
630 assertTrue(diff.getRemoved().isEmpty());
631 assertTrue(diff.getMissing().isEmpty());
632 assertTrue(diff.getModified().isEmpty());
633 assertEquals(1, diff.getConflicting().size());
634 assertTrue(diff.getConflicting().contains("b"));
635 assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
636 .get("b"));
637 assertTrue(diff.getUntrackedFolders().isEmpty());
638 }
639 }
640
641 @Test
642 public void testStageState_simulated_bug() throws Exception {
643 try (Git git = new Git(db)) {
644 writeTrashFile("a", "content");
645 git.add().addFilepattern("a").call();
646 RevCommit initialCommit = git.commit().setMessage("initial commit")
647 .call();
648
649
650 final String branchName = Constants.R_HEADS + "branch";
651 createBranch(initialCommit, branchName);
652 checkoutBranch(branchName);
653 writeTrashFile("b", "second file content - branch");
654 git.add().addFilepattern("b").call();
655 git.commit().setMessage("branch commit")
656 .call();
657
658
659 checkoutBranch(Constants.R_HEADS + Constants.MASTER);
660 writeTrashFile("b", "second file content - master");
661 git.add().addFilepattern("b").call();
662 git.commit().setMessage("master commit").call();
663
664
665 DirCacheBuilder builder = db.lockDirCache().builder();
666 DirCacheEntry entry = createEntry("a", FileMode.REGULAR_FILE, 0,
667 "content");
668 builder.add(entry);
669 entry = createEntry("b", FileMode.REGULAR_FILE, 2,
670 "second file content - master");
671 builder.add(entry);
672 entry = createEntry("b", FileMode.REGULAR_FILE, 3,
673 "second file content - branch");
674 builder.add(entry);
675 builder.commit();
676
677 FileTreeIterator iterator = new FileTreeIterator(db);
678 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
679 diff.diff();
680
681 assertTrue(diff.getChanged().isEmpty());
682 assertTrue(diff.getAdded().isEmpty());
683 assertTrue(diff.getRemoved().isEmpty());
684 assertTrue(diff.getMissing().isEmpty());
685 assertTrue(diff.getModified().isEmpty());
686 assertEquals(1, diff.getConflicting().size());
687 assertTrue(diff.getConflicting().contains("b"));
688 assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
689 .get("b"));
690 assertTrue(diff.getUntrackedFolders().isEmpty());
691 }
692 }
693
694 @Test
695 public void testAutoCRLFInput() throws Exception {
696 try (Git git = new Git(db)) {
697 FileBasedConfig config = db.getConfig();
698
699
700 config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
701 ConfigConstants.CONFIG_KEY_AUTOCRLF, AutoCRLF.FALSE);
702 config.save();
703
704
705 writeTrashFile("crlf.txt", "this\r\ncontains\r\ncrlf\r\n");
706 git.add().addFilepattern("crlf.txt").call();
707 git.commit().setMessage("Add crlf.txt").call();
708
709
710 config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
711 ConfigConstants.CONFIG_KEY_AUTOCRLF, AutoCRLF.INPUT);
712 config.save();
713
714 FileTreeIterator iterator = new FileTreeIterator(db);
715 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
716 diff.diff();
717
718 assertTrue(
719 "Expected no modified files, but there were: "
720 + diff.getModified(), diff.getModified().isEmpty());
721 }
722 }
723
724 private void verifyStageState(StageState expected, int... stages)
725 throws IOException {
726 DirCacheBuilder builder = db.lockDirCache().builder();
727 for (int stage : stages) {
728 DirCacheEntry entry = createEntry("a", FileMode.REGULAR_FILE,
729 stage, "content");
730 builder.add(entry);
731 }
732 builder.commit();
733
734 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
735 new FileTreeIterator(db));
736 diff.diff();
737
738 assertEquals(
739 "Conflict for entries in stages " + Arrays.toString(stages),
740 expected, diff.getConflictingStageStates().get("a"));
741 }
742
743 private void removeFromIndex(String path) throws IOException {
744 final DirCache dirc = db.lockDirCache();
745 final DirCacheEditor edit = dirc.editor();
746 edit.add(new DirCacheEditor.DeletePath(path));
747 if (!edit.commit())
748 throw new IOException("could not commit");
749 }
750
751 private void assumeUnchanged(String path) throws IOException {
752 final DirCache dirc = db.lockDirCache();
753 final DirCacheEntry ent = dirc.getEntry(path);
754 if (ent != null)
755 ent.setAssumeValid(true);
756 dirc.write();
757 if (!dirc.commit())
758 throw new IOException("could not commit");
759 }
760
761 }