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.diff;
44
45 import static org.eclipse.jgit.diff.DiffEntry.DEV_NULL;
46 import static org.eclipse.jgit.util.FileUtils.delete;
47 import static org.hamcrest.CoreMatchers.is;
48 import static org.hamcrest.CoreMatchers.notNullValue;
49 import static org.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertFalse;
51 import static org.junit.Assert.assertThat;
52 import static org.junit.Assert.assertTrue;
53
54 import java.io.File;
55 import java.util.List;
56
57 import org.eclipse.jgit.api.Git;
58 import org.eclipse.jgit.diff.DiffEntry.ChangeType;
59 import org.eclipse.jgit.dircache.DirCache;
60 import org.eclipse.jgit.dircache.DirCacheEditor;
61 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
62 import org.eclipse.jgit.dircache.DirCacheEntry;
63 import org.eclipse.jgit.junit.RepositoryTestCase;
64 import org.eclipse.jgit.lib.FileMode;
65 import org.eclipse.jgit.revwalk.RevCommit;
66 import org.eclipse.jgit.treewalk.EmptyTreeIterator;
67 import org.eclipse.jgit.treewalk.FileTreeIterator;
68 import org.eclipse.jgit.treewalk.TreeWalk;
69 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
70 import org.eclipse.jgit.treewalk.filter.TreeFilter;
71 import org.eclipse.jgit.util.FileUtils;
72 import org.junit.Test;
73
74 public class DiffEntryTest extends RepositoryTestCase {
75
76 @Test
77 public void shouldListAddedFileInInitialCommit() throws Exception {
78
79 writeTrashFile("a.txt", "content");
80 try (Git git = new Git(db);
81 TreeWalk walk = new TreeWalk(db)) {
82 git.add().addFilepattern("a.txt").call();
83 RevCommit c = git.commit().setMessage("initial commit").call();
84
85
86 walk.addTree(new EmptyTreeIterator());
87 walk.addTree(c.getTree());
88 List<DiffEntry> result = DiffEntry.scan(walk);
89
90
91 assertThat(result, notNullValue());
92 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
93
94 DiffEntry entry = result.get(0);
95 assertThat(entry.getChangeType(), is(ChangeType.ADD));
96 assertThat(entry.getNewPath(), is("a.txt"));
97 assertThat(entry.getOldPath(), is(DEV_NULL));
98 }
99 }
100
101 @Test
102 public void shouldListAddedFileBetweenTwoCommits() throws Exception {
103
104 try (Git git = new Git(db);
105 TreeWalk walk = new TreeWalk(db)) {
106 RevCommit c1 = git.commit().setMessage("initial commit").call();
107 writeTrashFile("a.txt", "content");
108 git.add().addFilepattern("a.txt").call();
109 RevCommit c2 = git.commit().setMessage("second commit").call();
110
111
112 walk.addTree(c1.getTree());
113 walk.addTree(c2.getTree());
114 List<DiffEntry> result = DiffEntry.scan(walk);
115
116
117 assertThat(result, notNullValue());
118 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
119
120 DiffEntry entry = result.get(0);
121 assertThat(entry.getChangeType(), is(ChangeType.ADD));
122 assertThat(entry.getNewPath(), is("a.txt"));
123 assertThat(entry.getOldPath(), is(DEV_NULL));
124 }
125 }
126
127 @Test
128 public void shouldListModificationBetweenTwoCommits() throws Exception {
129
130 try (Git git = new Git(db);
131 TreeWalk walk = new TreeWalk(db)) {
132 File file = writeTrashFile("a.txt", "content");
133 git.add().addFilepattern("a.txt").call();
134 RevCommit c1 = git.commit().setMessage("initial commit").call();
135 write(file, "new content");
136 RevCommit c2 = git.commit().setAll(true).setMessage("second commit")
137 .call();
138
139
140 walk.addTree(c1.getTree());
141 walk.addTree(c2.getTree());
142 List<DiffEntry> result = DiffEntry.scan(walk);
143
144
145 assertThat(result, notNullValue());
146 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
147
148 DiffEntry entry = result.get(0);
149 assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
150 assertThat(entry.getNewPath(), is("a.txt"));
151 }
152 }
153
154 @Test
155 public void shouldListDeletionBetweenTwoCommits() throws Exception {
156
157 try (Git git = new Git(db);
158 TreeWalk walk = new TreeWalk(db)) {
159 File file = writeTrashFile("a.txt", "content");
160 git.add().addFilepattern("a.txt").call();
161 RevCommit c1 = git.commit().setMessage("initial commit").call();
162 delete(file);
163 RevCommit c2 = git.commit().setAll(true).setMessage("delete a.txt")
164 .call();
165
166
167 walk.addTree(c1.getTree());
168 walk.addTree(c2.getTree());
169 List<DiffEntry> result = DiffEntry.scan(walk);
170
171
172 assertThat(result, notNullValue());
173 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
174
175 DiffEntry entry = result.get(0);
176 assertThat(entry.getOldPath(), is("a.txt"));
177 assertThat(entry.getNewPath(), is(DEV_NULL));
178 assertThat(entry.getChangeType(), is(ChangeType.DELETE));
179 }
180 }
181
182 @Test
183 public void shouldListModificationInDirWithoutModifiedTrees()
184 throws Exception {
185
186 try (Git git = new Git(db);
187 TreeWalk walk = new TreeWalk(db)) {
188 File tree = new File(new File(db.getWorkTree(), "a"), "b");
189 FileUtils.mkdirs(tree);
190 File file = new File(tree, "c.txt");
191 FileUtils.createNewFile(file);
192 write(file, "content");
193 git.add().addFilepattern("a").call();
194 RevCommit c1 = git.commit().setMessage("initial commit").call();
195 write(file, "new line");
196 RevCommit c2 = git.commit().setAll(true).setMessage("second commit")
197 .call();
198
199
200 walk.addTree(c1.getTree());
201 walk.addTree(c2.getTree());
202 walk.setRecursive(true);
203 List<DiffEntry> result = DiffEntry.scan(walk);
204
205
206 assertThat(result, notNullValue());
207 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
208
209 DiffEntry entry = result.get(0);
210 assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
211 assertThat(entry.getNewPath(), is("a/b/c.txt"));
212 }
213 }
214
215 @Test
216 public void shouldListModificationInDirWithModifiedTrees() throws Exception {
217
218 try (Git git = new Git(db);
219 TreeWalk walk = new TreeWalk(db)) {
220 File tree = new File(new File(db.getWorkTree(), "a"), "b");
221 FileUtils.mkdirs(tree);
222 File file = new File(tree, "c.txt");
223 FileUtils.createNewFile(file);
224 write(file, "content");
225 git.add().addFilepattern("a").call();
226 RevCommit c1 = git.commit().setMessage("initial commit").call();
227 write(file, "new line");
228 RevCommit c2 = git.commit().setAll(true).setMessage("second commit")
229 .call();
230
231
232 walk.addTree(c1.getTree());
233 walk.addTree(c2.getTree());
234 List<DiffEntry> result = DiffEntry.scan(walk, true);
235
236
237 assertThat(result, notNullValue());
238 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(3)));
239
240 DiffEntry entry = result.get(0);
241 assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
242 assertThat(entry.getNewPath(), is("a"));
243
244 entry = result.get(1);
245 assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
246 assertThat(entry.getNewPath(), is("a/b"));
247
248 entry = result.get(2);
249 assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
250 assertThat(entry.getNewPath(), is("a/b/c.txt"));
251 }
252 }
253
254 @Test
255 public void shouldListChangesInWorkingTree() throws Exception {
256
257 writeTrashFile("a.txt", "content");
258 try (Git git = new Git(db);
259 TreeWalk walk = new TreeWalk(db)) {
260 git.add().addFilepattern("a.txt").call();
261 RevCommit c = git.commit().setMessage("initial commit").call();
262 writeTrashFile("b.txt", "new line");
263
264
265 walk.addTree(c.getTree());
266 walk.addTree(new FileTreeIterator(db));
267 List<DiffEntry> result = DiffEntry.scan(walk, true);
268
269
270 assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
271 DiffEntry entry = result.get(0);
272
273 assertThat(entry.getChangeType(), is(ChangeType.ADD));
274 assertThat(entry.getNewPath(), is("b.txt"));
275 }
276 }
277
278 @Test
279 public void shouldMarkEntriesWhenGivenMarkTreeFilter() throws Exception {
280
281 try (Git git = new Git(db);
282 TreeWalk walk = new TreeWalk(db)) {
283 RevCommit c1 = git.commit().setMessage("initial commit").call();
284 FileUtils.mkdir(new File(db.getWorkTree(), "b"));
285 writeTrashFile("a.txt", "a");
286 writeTrashFile("b/1.txt", "b1");
287 writeTrashFile("b/2.txt", "b2");
288 writeTrashFile("c.txt", "c");
289 git.add().addFilepattern("a.txt").addFilepattern("b")
290 .addFilepattern("c.txt").call();
291 RevCommit c2 = git.commit().setMessage("second commit").call();
292 TreeFilter filterA = PathFilterGroup.createFromStrings("a.txt");
293 TreeFilter filterB = PathFilterGroup.createFromStrings("b");
294 TreeFilter filterB2 = PathFilterGroup.createFromStrings("b/2.txt");
295
296
297 walk.addTree(c1.getTree());
298 walk.addTree(c2.getTree());
299 List<DiffEntry> result = DiffEntry.scan(walk, true, new TreeFilter[] {
300 filterA, filterB, filterB2 });
301
302
303 assertThat(result, notNullValue());
304 assertEquals(5, result.size());
305
306 DiffEntry entryA = result.get(0);
307 DiffEntry entryB = result.get(1);
308 DiffEntry entryB1 = result.get(2);
309 DiffEntry entryB2 = result.get(3);
310 DiffEntry entryC = result.get(4);
311
312 assertThat(entryA.getNewPath(), is("a.txt"));
313 assertTrue(entryA.isMarked(0));
314 assertFalse(entryA.isMarked(1));
315 assertFalse(entryA.isMarked(2));
316 assertEquals(1, entryA.getTreeFilterMarks());
317
318 assertThat(entryB.getNewPath(), is("b"));
319 assertFalse(entryB.isMarked(0));
320 assertTrue(entryB.isMarked(1));
321 assertTrue(entryB.isMarked(2));
322 assertEquals(6, entryB.getTreeFilterMarks());
323
324 assertThat(entryB1.getNewPath(), is("b/1.txt"));
325 assertFalse(entryB1.isMarked(0));
326 assertTrue(entryB1.isMarked(1));
327 assertFalse(entryB1.isMarked(2));
328 assertEquals(2, entryB1.getTreeFilterMarks());
329
330 assertThat(entryB2.getNewPath(), is("b/2.txt"));
331 assertFalse(entryB2.isMarked(0));
332 assertTrue(entryB2.isMarked(1));
333 assertTrue(entryB2.isMarked(2));
334 assertEquals(6, entryB2.getTreeFilterMarks());
335
336 assertThat(entryC.getNewPath(), is("c.txt"));
337 assertFalse(entryC.isMarked(0));
338 assertFalse(entryC.isMarked(1));
339 assertFalse(entryC.isMarked(2));
340 assertEquals(0, entryC.getTreeFilterMarks());
341 }
342 }
343
344 @Test(expected = IllegalArgumentException.class)
345 public void shouldThrowIAEWhenTreeWalkHasLessThanTwoTrees()
346 throws Exception {
347
348
349
350 try (TreeWalk walk = new TreeWalk(db)) {
351 walk.addTree(new EmptyTreeIterator());
352 DiffEntry.scan(walk);
353 }
354 }
355
356 @Test(expected = IllegalArgumentException.class)
357 public void shouldThrowIAEWhenTreeWalkHasMoreThanTwoTrees()
358 throws Exception {
359
360
361
362 try (TreeWalk walk = new TreeWalk(db)) {
363 walk.addTree(new EmptyTreeIterator());
364 walk.addTree(new EmptyTreeIterator());
365 walk.addTree(new EmptyTreeIterator());
366 DiffEntry.scan(walk);
367 }
368 }
369
370 @Test(expected = IllegalArgumentException.class)
371 public void shouldThrowIAEWhenScanShouldIncludeTreesAndWalkIsRecursive()
372 throws Exception {
373
374
375
376 try (TreeWalk walk = new TreeWalk(db)) {
377 walk.addTree(new EmptyTreeIterator());
378 walk.addTree(new EmptyTreeIterator());
379 walk.setRecursive(true);
380 DiffEntry.scan(walk, true);
381 }
382 }
383
384 @Test
385 public void shouldReportFileModeChange() throws Exception {
386 writeTrashFile("a.txt", "content");
387 try (Git git = new Git(db);
388 TreeWalk walk = new TreeWalk(db)) {
389 git.add().addFilepattern("a.txt").call();
390 RevCommit c1 = git.commit().setMessage("initial commit").call();
391 DirCache cache = db.lockDirCache();
392 DirCacheEditor editor = cache.editor();
393 walk.addTree(c1.getTree());
394 walk.setRecursive(true);
395 assertTrue(walk.next());
396
397 editor.add(new PathEdit("a.txt") {
398 @Override
399 public void apply(DirCacheEntry ent) {
400 ent.setFileMode(FileMode.EXECUTABLE_FILE);
401 ent.setObjectId(walk.getObjectId(0));
402 }
403 });
404 assertTrue(editor.commit());
405 RevCommit c2 = git.commit().setMessage("second commit").call();
406 walk.reset();
407 walk.addTree(c1.getTree());
408 walk.addTree(c2.getTree());
409 List<DiffEntry> diffs = DiffEntry.scan(walk, false);
410 assertEquals(1, diffs.size());
411 DiffEntry diff = diffs.get(0);
412 assertEquals(ChangeType.MODIFY,diff.getChangeType());
413 assertEquals(diff.getOldId(), diff.getNewId());
414 assertEquals("a.txt", diff.getOldPath());
415 assertEquals(diff.getOldPath(), diff.getNewPath());
416 assertEquals(FileMode.EXECUTABLE_FILE, diff.getNewMode());
417 assertEquals(FileMode.REGULAR_FILE, diff.getOldMode());
418 }
419 }
420 }