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
44 package org.eclipse.jgit.lib;
45
46 import static org.junit.Assert.assertArrayEquals;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertFalse;
49 import static org.junit.Assert.assertTrue;
50
51 import java.io.File;
52 import java.io.IOException;
53 import java.util.Arrays;
54 import java.util.Set;
55
56 import org.eclipse.jgit.api.CloneCommand;
57 import org.eclipse.jgit.api.Git;
58 import org.eclipse.jgit.api.errors.GitAPIException;
59 import org.eclipse.jgit.errors.NoWorkTreeException;
60 import org.eclipse.jgit.internal.storage.file.FileRepository;
61 import org.eclipse.jgit.junit.JGitTestUtil;
62 import org.eclipse.jgit.junit.RepositoryTestCase;
63 import org.eclipse.jgit.submodule.SubmoduleWalk.IgnoreSubmoduleMode;
64 import org.eclipse.jgit.treewalk.FileTreeIterator;
65 import org.junit.Before;
66 import org.junit.experimental.theories.DataPoints;
67 import org.junit.experimental.theories.Theories;
68 import org.junit.experimental.theories.Theory;
69 import org.junit.runner.RunWith;
70
71 @RunWith(Theories.class)
72 public class IndexDiffSubmoduleTest extends RepositoryTestCase {
73
74 protected FileRepository submodule_db;
75
76
77 protected File submodule_trash;
78
79 @DataPoints
80 public static IgnoreSubmoduleMode allModes[] = IgnoreSubmoduleMode.values();
81
82 @Override
83 @Before
84 public void setUp() throws Exception {
85 super.setUp();
86 FileRepository submoduleStandalone = createWorkRepository();
87 JGitTestUtil.writeTrashFile(submoduleStandalone, "fileInSubmodule",
88 "submodule");
89 Git submoduleStandaloneGit = Git.wrap(submoduleStandalone);
90 submoduleStandaloneGit.add().addFilepattern("fileInSubmodule").call();
91 submoduleStandaloneGit.commit().setMessage("add file to submodule")
92 .call();
93
94 submodule_db = (FileRepository) Git.wrap(db).submoduleAdd()
95 .setPath("modules/submodule")
96 .setURI(submoduleStandalone.getDirectory().toURI().toString())
97 .call();
98 submodule_trash = submodule_db.getWorkTree();
99 addRepoToClose(submodule_db);
100 writeTrashFile("fileInRoot", "root");
101 Git rootGit = Git.wrap(db);
102 rootGit.add().addFilepattern("fileInRoot").call();
103 rootGit.commit().setMessage("add submodule and root file").call();
104 }
105
106 @Theory
107 public void testInitiallyClean(IgnoreSubmoduleMode mode)
108 throws IOException {
109 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
110 new FileTreeIterator(db));
111 indexDiff.setIgnoreSubmoduleMode(mode);
112 assertFalse(indexDiff.diff());
113 }
114
115 private Repository cloneWithoutCloningSubmodule() throws Exception {
116 File directory = createTempDirectory(
117 "testCloneWithoutCloningSubmodules");
118 CloneCommand clone = Git.cloneRepository();
119 clone.setDirectory(directory);
120 clone.setCloneSubmodules(false);
121 clone.setURI(db.getDirectory().toURI().toString());
122 Git git2 = clone.call();
123 addRepoToClose(git2.getRepository());
124 return git2.getRepository();
125 }
126
127 @Theory
128 public void testCleanAfterClone(IgnoreSubmoduleMode mode) throws Exception {
129 Repository db2 = cloneWithoutCloningSubmodule();
130 IndexDiff indexDiff = new IndexDiff(db2, Constants.HEAD,
131 new FileTreeIterator(db2));
132 indexDiff.setIgnoreSubmoduleMode(mode);
133 boolean changed = indexDiff.diff();
134 assertFalse(changed);
135 }
136
137 @Theory
138 public void testMissingIfDirectoryGone(IgnoreSubmoduleMode mode)
139 throws Exception {
140 recursiveDelete(submodule_trash);
141 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
142 new FileTreeIterator(db));
143 indexDiff.setIgnoreSubmoduleMode(mode);
144 boolean hasChanges = indexDiff.diff();
145 if (mode != IgnoreSubmoduleMode.ALL) {
146 assertTrue(hasChanges);
147 assertEquals("[modules/submodule]",
148 indexDiff.getMissing().toString());
149 } else {
150 assertFalse(hasChanges);
151 }
152 }
153
154 @Theory
155 public void testSubmoduleReplacedByFile(IgnoreSubmoduleMode mode)
156 throws Exception {
157 recursiveDelete(submodule_trash);
158 writeTrashFile("modules/submodule", "nonsense");
159 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
160 new FileTreeIterator(db));
161 indexDiff.setIgnoreSubmoduleMode(mode);
162 assertTrue(indexDiff.diff());
163 assertEquals("[]", indexDiff.getMissing().toString());
164 assertEquals("[]", indexDiff.getUntracked().toString());
165 assertEquals("[modules/submodule]", indexDiff.getModified().toString());
166 }
167
168 @Theory
169 public void testDirtyRootWorktree(IgnoreSubmoduleMode mode)
170 throws IOException {
171 writeTrashFile("fileInRoot", "2");
172
173 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
174 new FileTreeIterator(db));
175 indexDiff.setIgnoreSubmoduleMode(mode);
176 assertTrue(indexDiff.diff());
177 }
178
179 private void assertDiff(IndexDiff indexDiff, IgnoreSubmoduleMode mode,
180 IgnoreSubmoduleMode... expectedEmptyModes) throws IOException {
181 boolean diffResult = indexDiff.diff();
182 Set<String> submodulePaths = indexDiff
183 .getPathsWithIndexMode(FileMode.GITLINK);
184 boolean emptyExpected = false;
185 for (IgnoreSubmoduleMode empty : expectedEmptyModes) {
186 if (mode.equals(empty)) {
187 emptyExpected = true;
188 break;
189 }
190 }
191 if (emptyExpected) {
192 assertFalse("diff should be false with mode=" + mode,
193 diffResult);
194 assertEquals("should have no paths with FileMode.GITLINK", 0,
195 submodulePaths.size());
196 } else {
197 assertTrue("diff should be true with mode=" + mode,
198 diffResult);
199 assertTrue("submodule path should have FileMode.GITLINK",
200 submodulePaths.contains("modules/submodule"));
201 }
202 }
203
204 @Theory
205 public void testDirtySubmoduleWorktree(IgnoreSubmoduleMode mode)
206 throws IOException {
207 JGitTestUtil.writeTrashFile(submodule_db, "fileInSubmodule", "2");
208 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
209 new FileTreeIterator(db));
210 indexDiff.setIgnoreSubmoduleMode(mode);
211 assertDiff(indexDiff, mode, IgnoreSubmoduleMode.ALL,
212 IgnoreSubmoduleMode.DIRTY);
213 }
214
215 @Theory
216 public void testDirtySubmoduleHEAD(IgnoreSubmoduleMode mode)
217 throws IOException, GitAPIException {
218 JGitTestUtil.writeTrashFile(submodule_db, "fileInSubmodule", "2");
219 Git submoduleGit = Git.wrap(submodule_db);
220 submoduleGit.add().addFilepattern("fileInSubmodule").call();
221 submoduleGit.commit().setMessage("Modified fileInSubmodule").call();
222
223 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
224 new FileTreeIterator(db));
225 indexDiff.setIgnoreSubmoduleMode(mode);
226 assertDiff(indexDiff, mode, IgnoreSubmoduleMode.ALL);
227 }
228
229 @Theory
230 public void testDirtySubmoduleIndex(IgnoreSubmoduleMode mode)
231 throws IOException, GitAPIException {
232 JGitTestUtil.writeTrashFile(submodule_db, "fileInSubmodule", "2");
233 Git submoduleGit = Git.wrap(submodule_db);
234 submoduleGit.add().addFilepattern("fileInSubmodule").call();
235
236 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
237 new FileTreeIterator(db));
238 indexDiff.setIgnoreSubmoduleMode(mode);
239 assertDiff(indexDiff, mode, IgnoreSubmoduleMode.ALL,
240 IgnoreSubmoduleMode.DIRTY);
241 }
242
243 @Theory
244 public void testDirtySubmoduleIndexAndWorktree(IgnoreSubmoduleMode mode)
245 throws IOException, GitAPIException, NoWorkTreeException {
246 JGitTestUtil.writeTrashFile(submodule_db, "fileInSubmodule", "2");
247 Git submoduleGit = Git.wrap(submodule_db);
248 submoduleGit.add().addFilepattern("fileInSubmodule").call();
249 JGitTestUtil.writeTrashFile(submodule_db, "fileInSubmodule", "3");
250
251 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
252 new FileTreeIterator(db));
253 indexDiff.setIgnoreSubmoduleMode(mode);
254 assertDiff(indexDiff, mode, IgnoreSubmoduleMode.ALL,
255 IgnoreSubmoduleMode.DIRTY);
256 }
257
258 @Theory
259 public void testDirtySubmoduleWorktreeUntracked(IgnoreSubmoduleMode mode)
260 throws IOException {
261 JGitTestUtil.writeTrashFile(submodule_db, "additionalFileInSubmodule",
262 "2");
263 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
264 new FileTreeIterator(db));
265 indexDiff.setIgnoreSubmoduleMode(mode);
266 assertDiff(indexDiff, mode, IgnoreSubmoduleMode.ALL,
267 IgnoreSubmoduleMode.DIRTY, IgnoreSubmoduleMode.UNTRACKED);
268 }
269
270 @Theory
271 public void testSubmoduleReplacedByMovedFile(IgnoreSubmoduleMode mode)
272 throws Exception {
273 Git git = Git.wrap(db);
274 git.rm().setCached(true).addFilepattern("modules/submodule").call();
275 recursiveDelete(submodule_trash);
276 JGitTestUtil.deleteTrashFile(db, "fileInRoot");
277
278 writeTrashFile("modules/submodule/fileInRoot", "root");
279 git.rm().addFilepattern("fileInRoot").addFilepattern("modules/").call();
280 git.add().addFilepattern("modules/").call();
281 IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD,
282 new FileTreeIterator(db));
283 indexDiff.setIgnoreSubmoduleMode(mode);
284 assertTrue(indexDiff.diff());
285 String[] removed = indexDiff.getRemoved().toArray(new String[0]);
286 Arrays.sort(removed);
287 if (IgnoreSubmoduleMode.ALL.equals(mode)) {
288 assertArrayEquals(new String[] { "fileInRoot" }, removed);
289 } else {
290 assertArrayEquals(
291 new String[] { "fileInRoot", "modules/submodule" },
292 removed);
293 }
294 assertEquals("[modules/submodule/fileInRoot]",
295 indexDiff.getAdded().toString());
296 }
297
298 }