View Javadoc
1   /*
2    * Copyright (C) 2011, Tomasz Zarna <Tomasz.Zarna@pl.ibm.com> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.api;
11  
12  import static org.junit.Assert.assertEquals;
13  import static org.junit.Assert.assertNotNull;
14  
15  import java.io.ByteArrayOutputStream;
16  import java.io.File;
17  import java.io.IOException;
18  import java.io.OutputStream;
19  import java.util.List;
20  
21  import org.eclipse.jgit.diff.DiffEntry;
22  import org.eclipse.jgit.diff.DiffEntry.ChangeType;
23  import org.eclipse.jgit.junit.RepositoryTestCase;
24  import org.eclipse.jgit.junit.time.TimeUtil;
25  import org.eclipse.jgit.lib.ObjectId;
26  import org.eclipse.jgit.lib.ObjectReader;
27  import org.eclipse.jgit.revwalk.RevWalk;
28  import org.eclipse.jgit.treewalk.AbstractTreeIterator;
29  import org.eclipse.jgit.treewalk.CanonicalTreeParser;
30  import org.eclipse.jgit.treewalk.filter.PathFilter;
31  import org.junit.Test;
32  
33  public class DiffCommandTest extends RepositoryTestCase {
34  	@Test
35  	public void testDiffModified() throws Exception {
36  		write(new File(db.getWorkTree(), "test.txt"), "test");
37  		File folder = new File(db.getWorkTree(), "folder");
38  		folder.mkdir();
39  		write(new File(folder, "folder.txt"), "folder");
40  		try (Git git = new Git(db)) {
41  			git.add().addFilepattern(".").call();
42  			git.commit().setMessage("Initial commit").call();
43  			write(new File(folder, "folder.txt"), "folder change");
44  
45  			OutputStream out = new ByteArrayOutputStream();
46  			List<DiffEntry> entries = git.diff().setOutputStream(out).call();
47  			assertEquals(1, entries.size());
48  			assertEquals(ChangeType.MODIFY, entries.get(0)
49  					.getChangeType());
50  			assertEquals("folder/folder.txt", entries.get(0)
51  					.getOldPath());
52  			assertEquals("folder/folder.txt", entries.get(0)
53  					.getNewPath());
54  
55  			String actual = out.toString();
56  			String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
57  					+ "index 0119635..95c4c65 100644\n"
58  					+ "--- a/folder/folder.txt\n"
59  					+ "+++ b/folder/folder.txt\n"
60  					+ "@@ -1 +1 @@\n"
61  					+ "-folder\n"
62  					+ "\\ No newline at end of file\n"
63  					+ "+folder change\n"
64  					+ "\\ No newline at end of file\n";
65  			assertEquals(expected, actual);
66  		}
67  	}
68  
69  	@Test
70  	public void testDiffCached() throws Exception {
71  		write(new File(db.getWorkTree(), "test.txt"), "test");
72  		File folder = new File(db.getWorkTree(), "folder");
73  		folder.mkdir();
74  		try (Git git = new Git(db)) {
75  			git.add().addFilepattern(".").call();
76  			git.commit().setMessage("Initial commit").call();
77  			write(new File(folder, "folder.txt"), "folder");
78  			git.add().addFilepattern(".").call();
79  
80  			OutputStream out = new ByteArrayOutputStream();
81  			List<DiffEntry> entries = git.diff().setOutputStream(out)
82  					.setCached(true).call();
83  			assertEquals(1, entries.size());
84  			assertEquals(ChangeType.ADD, entries.get(0)
85  					.getChangeType());
86  			assertEquals("/dev/null", entries.get(0)
87  					.getOldPath());
88  			assertEquals("folder/folder.txt", entries.get(0)
89  					.getNewPath());
90  
91  			String actual = out.toString();
92  			String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
93  					+ "new file mode 100644\n"
94  					+ "index 0000000..0119635\n"
95  					+ "--- /dev/null\n"
96  					+ "+++ b/folder/folder.txt\n"
97  					+ "@@ -0,0 +1 @@\n"
98  					+ "+folder\n"
99  					+ "\\ No newline at end of file\n";
100 			assertEquals(expected, actual);
101 		}
102 	}
103 
104 	@Test
105 	public void testDiffTwoCommits() throws Exception {
106 		write(new File(db.getWorkTree(), "test.txt"), "test");
107 		File folder = new File(db.getWorkTree(), "folder");
108 		folder.mkdir();
109 		write(new File(folder, "folder.txt"), "folder");
110 		try (Git git = new Git(db)) {
111 			git.add().addFilepattern(".").call();
112 			git.commit().setMessage("Initial commit").call();
113 			write(new File(folder, "folder.txt"), "folder change");
114 			git.add().addFilepattern(".").call();
115 			git.commit().setMessage("second commit").call();
116 			write(new File(folder, "folder.txt"), "second folder change");
117 			git.add().addFilepattern(".").call();
118 			git.commit().setMessage("third commit").call();
119 
120 			// bad filter
121 			DiffCommand diff = git.diff().setShowNameAndStatusOnly(true)
122 					.setPathFilter(PathFilter.create("test.txt"))
123 					.setOldTree(getTreeIterator("HEAD^^"))
124 					.setNewTree(getTreeIterator("HEAD^"));
125 			List<DiffEntry> entries = diff.call();
126 			assertEquals(0, entries.size());
127 
128 			// no filter, two commits
129 			OutputStream out = new ByteArrayOutputStream();
130 			diff = git.diff().setOutputStream(out)
131 					.setOldTree(getTreeIterator("HEAD^^"))
132 					.setNewTree(getTreeIterator("HEAD^"));
133 			entries = diff.call();
134 			assertEquals(1, entries.size());
135 			assertEquals(ChangeType.MODIFY, entries.get(0).getChangeType());
136 			assertEquals("folder/folder.txt", entries.get(0).getOldPath());
137 			assertEquals("folder/folder.txt", entries.get(0).getNewPath());
138 
139 			String actual = out.toString();
140 			String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
141 					+ "index 0119635..95c4c65 100644\n"
142 					+ "--- a/folder/folder.txt\n"
143 					+ "+++ b/folder/folder.txt\n"
144 					+ "@@ -1 +1 @@\n"
145 					+ "-folder\n"
146 					+ "\\ No newline at end of file\n"
147 					+ "+folder change\n"
148 					+ "\\ No newline at end of file\n";
149 			assertEquals(expected, actual);
150 		}
151 	}
152 
153 	@Test
154 	public void testDiffWithPrefixes() throws Exception {
155 		write(new File(db.getWorkTree(), "test.txt"), "test");
156 		try (Git git = new Git(db)) {
157 			git.add().addFilepattern(".").call();
158 			git.commit().setMessage("Initial commit").call();
159 			write(new File(db.getWorkTree(), "test.txt"), "test change");
160 
161 			OutputStream out = new ByteArrayOutputStream();
162 			git.diff().setOutputStream(out).setSourcePrefix("old/")
163 					.setDestinationPrefix("new/").call();
164 
165 			String actual = out.toString();
166 			String expected = "diff --git old/test.txt new/test.txt\n"
167 					+ "index 30d74d2..4dba797 100644\n" + "--- old/test.txt\n"
168 					+ "+++ new/test.txt\n" + "@@ -1 +1 @@\n" + "-test\n"
169 					+ "\\ No newline at end of file\n" + "+test change\n"
170 					+ "\\ No newline at end of file\n";
171 			assertEquals(expected, actual);
172 		}
173 	}
174 
175 	@Test
176 	public void testDiffWithNegativeLineCount() throws Exception {
177 		write(new File(db.getWorkTree(), "test.txt"),
178 				"0\n1\n2\n3\n4\n5\n6\n7\n8\n9");
179 		try (Git git = new Git(db)) {
180 			git.add().addFilepattern(".").call();
181 			git.commit().setMessage("Initial commit").call();
182 			write(new File(db.getWorkTree(), "test.txt"),
183 					"0\n1\n2\n3\n4a\n5\n6\n7\n8\n9");
184 
185 			OutputStream out = new ByteArrayOutputStream();
186 			git.diff().setOutputStream(out).setContextLines(1).call();
187 
188 			String actual = out.toString();
189 			String expected = "diff --git a/test.txt b/test.txt\n"
190 					+ "index f55b5c9..c5ec8fd 100644\n" + "--- a/test.txt\n"
191 					+ "+++ b/test.txt\n" + "@@ -4,3 +4,3 @@\n" + " 3\n" + "-4\n"
192 					+ "+4a\n" + " 5\n";
193 			assertEquals(expected, actual);
194 		}
195 	}
196 
197 	@Test
198 	public void testNoOutputStreamSet() throws Exception {
199 		File file = writeTrashFile("test.txt", "a");
200 		TimeUtil.setLastModifiedWithOffset(file.toPath(), -5000L);
201 		try (Git git = new Git(db)) {
202 			git.add().addFilepattern(".").call();
203 			write(file, "b");
204 
205 			List<DiffEntry> diffs = git.diff().call();
206 			assertNotNull(diffs);
207 			assertEquals(1, diffs.size());
208 			DiffEntry diff = diffs.get(0);
209 			assertEquals(ChangeType.MODIFY, diff.getChangeType());
210 			assertEquals("test.txt", diff.getOldPath());
211 			assertEquals("test.txt", diff.getNewPath());
212 		}
213 	}
214 
215 	private AbstractTreeIterator getTreeIterator(String name)
216 			throws IOException {
217 		final ObjectId id = db.resolve(name);
218 		if (id == null)
219 			throw new IllegalArgumentException(name);
220 		final CanonicalTreeParser p = new CanonicalTreeParser();
221 		try (ObjectReader or = db.newObjectReader();
222 				RevWalk rw = new RevWalk(db)) {
223 			p.reset(or, rw.parseTree(id));
224 			return p;
225 		}
226 	}
227 }