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.submodule;
44
45 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PATH;
46 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_URL;
47 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_SUBMODULE_SECTION;
48 import static org.eclipse.jgit.lib.Constants.DOT_GIT_MODULES;
49 import static org.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertFalse;
51 import static org.junit.Assert.assertNotNull;
52 import static org.junit.Assert.assertNull;
53 import static org.junit.Assert.assertTrue;
54
55 import java.io.File;
56 import java.io.FileWriter;
57 import java.io.IOException;
58
59 import org.eclipse.jgit.api.Git;
60 import org.eclipse.jgit.api.Status;
61 import org.eclipse.jgit.api.errors.GitAPIException;
62 import org.eclipse.jgit.dircache.DirCache;
63 import org.eclipse.jgit.dircache.DirCacheEditor;
64 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
65 import org.eclipse.jgit.dircache.DirCacheEntry;
66 import org.eclipse.jgit.errors.ConfigInvalidException;
67 import org.eclipse.jgit.errors.NoWorkTreeException;
68 import org.eclipse.jgit.internal.storage.file.FileRepository;
69 import org.eclipse.jgit.junit.RepositoryTestCase;
70 import org.eclipse.jgit.junit.TestRepository;
71 import org.eclipse.jgit.lib.Config;
72 import org.eclipse.jgit.lib.Constants;
73 import org.eclipse.jgit.lib.FileMode;
74 import org.eclipse.jgit.lib.ObjectId;
75 import org.eclipse.jgit.lib.Repository;
76 import org.eclipse.jgit.revwalk.RevBlob;
77 import org.eclipse.jgit.revwalk.RevCommit;
78 import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
79 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
80 import org.eclipse.jgit.treewalk.filter.PathFilter;
81 import org.junit.Before;
82 import org.junit.Test;
83
84
85
86
87 public class SubmoduleWalkTest extends RepositoryTestCase {
88 private TestRepository<Repository> testDb;
89
90 @Before
91 public void setUp() throws Exception {
92 super.setUp();
93 testDb = new TestRepository<Repository>(db);
94 }
95
96 @Test
97 public void repositoryWithNoSubmodules() throws IOException {
98 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
99 assertFalse(gen.next());
100 assertNull(gen.getPath());
101 assertEquals(ObjectId.zeroId(), gen.getObjectId());
102 }
103
104 @Test
105 public void bareRepositoryWithNoSubmodules() throws IOException {
106 FileRepository bareRepo = createBareRepository();
107 boolean result = SubmoduleWalk.containsGitModulesFile(bareRepo);
108 assertFalse(result);
109 }
110
111 @Test
112 public void repositoryWithRootLevelSubmodule() throws IOException,
113 ConfigInvalidException, NoWorkTreeException, GitAPIException {
114 final ObjectId id = ObjectId
115 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
116 final String path = "sub";
117 DirCache cache = db.lockDirCache();
118 DirCacheEditor editor = cache.editor();
119 editor.add(new PathEdit(path) {
120
121 public void apply(DirCacheEntry ent) {
122 ent.setFileMode(FileMode.GITLINK);
123 ent.setObjectId(id);
124 }
125 });
126 editor.commit();
127
128 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
129 assertTrue(gen.next());
130 assertEquals(path, gen.getPath());
131 assertEquals(id, gen.getObjectId());
132 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
133 assertNull(gen.getConfigUpdate());
134 assertNull(gen.getConfigUrl());
135 assertNull(gen.getModulesPath());
136 assertNull(gen.getModulesUpdate());
137 assertNull(gen.getModulesUrl());
138 assertNull(gen.getRepository());
139 Status status = Git.wrap(db).status().call();
140 assertTrue(!status.isClean());
141 assertFalse(gen.next());
142 }
143
144 @SuppressWarnings("resource" )
145 @Test
146 public void repositoryWithRootLevelSubmoduleAbsoluteRef()
147 throws IOException, ConfigInvalidException {
148 final ObjectId id = ObjectId
149 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
150 final String path = "sub";
151 File dotGit = new File(db.getWorkTree(), path + File.separatorChar
152 + Constants.DOT_GIT);
153 if (!dotGit.getParentFile().exists())
154 dotGit.getParentFile().mkdirs();
155
156 File modulesGitDir = new File(db.getDirectory(), "modules"
157 + File.separatorChar + path);
158 new FileWriter(dotGit).append(
159 "gitdir: " + modulesGitDir.getAbsolutePath()).close();
160 FileRepositoryBuilder builder = new FileRepositoryBuilder();
161 builder.setWorkTree(new File(db.getWorkTree(), path));
162 builder.build().create();
163
164 DirCache cache = db.lockDirCache();
165 DirCacheEditor editor = cache.editor();
166 editor.add(new PathEdit(path) {
167
168 public void apply(DirCacheEntry ent) {
169 ent.setFileMode(FileMode.GITLINK);
170 ent.setObjectId(id);
171 }
172 });
173 editor.commit();
174
175 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
176 assertTrue(gen.next());
177 assertEquals(path, gen.getPath());
178 assertEquals(id, gen.getObjectId());
179 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
180 assertNull(gen.getConfigUpdate());
181 assertNull(gen.getConfigUrl());
182 assertNull(gen.getModulesPath());
183 assertNull(gen.getModulesUpdate());
184 assertNull(gen.getModulesUrl());
185 Repository subRepo = gen.getRepository();
186 assertNotNull(subRepo);
187 assertEquals(modulesGitDir.getAbsolutePath(),
188 subRepo.getDirectory().getAbsolutePath());
189 assertEquals(new File(db.getWorkTree(), path).getAbsolutePath(),
190 subRepo.getWorkTree().getAbsolutePath());
191 subRepo.close();
192 assertFalse(gen.next());
193 }
194
195 @SuppressWarnings("resource" )
196 @Test
197 public void repositoryWithRootLevelSubmoduleRelativeRef()
198 throws IOException, ConfigInvalidException {
199 final ObjectId id = ObjectId
200 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
201 final String path = "sub";
202 File dotGit = new File(db.getWorkTree(), path + File.separatorChar
203 + Constants.DOT_GIT);
204 if (!dotGit.getParentFile().exists())
205 dotGit.getParentFile().mkdirs();
206
207 File modulesGitDir = new File(db.getDirectory(), "modules"
208 + File.separatorChar + path);
209 new FileWriter(dotGit).append(
210 "gitdir: " + "../" + Constants.DOT_GIT + "/modules/" + path)
211 .close();
212 FileRepositoryBuilder builder = new FileRepositoryBuilder();
213 builder.setWorkTree(new File(db.getWorkTree(), path));
214 builder.build().create();
215
216 DirCache cache = db.lockDirCache();
217 DirCacheEditor editor = cache.editor();
218 editor.add(new PathEdit(path) {
219
220 public void apply(DirCacheEntry ent) {
221 ent.setFileMode(FileMode.GITLINK);
222 ent.setObjectId(id);
223 }
224 });
225 editor.commit();
226
227 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
228 assertTrue(gen.next());
229 assertEquals(path, gen.getPath());
230 assertEquals(id, gen.getObjectId());
231 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
232 assertNull(gen.getConfigUpdate());
233 assertNull(gen.getConfigUrl());
234 assertNull(gen.getModulesPath());
235 assertNull(gen.getModulesUpdate());
236 assertNull(gen.getModulesUrl());
237 Repository subRepo = gen.getRepository();
238 assertNotNull(subRepo);
239 assertEqualsFile(modulesGitDir, subRepo.getDirectory());
240 assertEqualsFile(new File(db.getWorkTree(), path),
241 subRepo.getWorkTree());
242 subRepo.close();
243 assertFalse(gen.next());
244 }
245
246 @Test
247 public void repositoryWithNestedSubmodule() throws IOException,
248 ConfigInvalidException {
249 final ObjectId id = ObjectId
250 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
251 final String path = "sub/dir/final";
252 DirCache cache = db.lockDirCache();
253 DirCacheEditor editor = cache.editor();
254 editor.add(new PathEdit(path) {
255
256 public void apply(DirCacheEntry ent) {
257 ent.setFileMode(FileMode.GITLINK);
258 ent.setObjectId(id);
259 }
260 });
261 editor.commit();
262
263 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
264 assertTrue(gen.next());
265 assertEquals(path, gen.getPath());
266 assertEquals(id, gen.getObjectId());
267 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
268 assertNull(gen.getConfigUpdate());
269 assertNull(gen.getConfigUrl());
270 assertNull(gen.getModulesPath());
271 assertNull(gen.getModulesUpdate());
272 assertNull(gen.getModulesUrl());
273 assertNull(gen.getRepository());
274 assertFalse(gen.next());
275 }
276
277 @Test
278 public void generatorFilteredToOneOfTwoSubmodules() throws IOException {
279 final ObjectId id1 = ObjectId
280 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
281 final String path1 = "sub1";
282 final ObjectId id2 = ObjectId
283 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1235");
284 final String path2 = "sub2";
285 DirCache cache = db.lockDirCache();
286 DirCacheEditor editor = cache.editor();
287 editor.add(new PathEdit(path1) {
288
289 public void apply(DirCacheEntry ent) {
290 ent.setFileMode(FileMode.GITLINK);
291 ent.setObjectId(id1);
292 }
293 });
294 editor.add(new PathEdit(path2) {
295
296 public void apply(DirCacheEntry ent) {
297 ent.setFileMode(FileMode.GITLINK);
298 ent.setObjectId(id2);
299 }
300 });
301 editor.commit();
302
303 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
304 gen.setFilter(PathFilter.create(path1));
305 assertTrue(gen.next());
306 assertEquals(path1, gen.getPath());
307 assertEquals(id1, gen.getObjectId());
308 assertFalse(gen.next());
309 }
310
311 @Test
312 public void indexWithGitmodules() throws Exception {
313 final ObjectId subId = ObjectId
314 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
315 final String path = "sub";
316
317 final Config gitmodules = new Config();
318 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_PATH,
319 "sub");
320
321 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
322 "git://example.com/bad");
323 final RevBlob gitmodulesBlob = testDb.blob(gitmodules.toText());
324
325 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
326 "git://example.com/sub");
327 writeTrashFile(DOT_GIT_MODULES, gitmodules.toText());
328
329 DirCache cache = db.lockDirCache();
330 DirCacheEditor editor = cache.editor();
331 editor.add(new PathEdit(path) {
332
333 public void apply(DirCacheEntry ent) {
334 ent.setFileMode(FileMode.GITLINK);
335 ent.setObjectId(subId);
336 }
337 });
338 editor.add(new PathEdit(DOT_GIT_MODULES) {
339
340 public void apply(DirCacheEntry ent) {
341 ent.setFileMode(FileMode.REGULAR_FILE);
342 ent.setObjectId(gitmodulesBlob);
343 }
344 });
345 editor.commit();
346
347 SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
348 assertTrue(gen.next());
349 assertEquals(path, gen.getPath());
350 assertEquals(subId, gen.getObjectId());
351 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
352 assertNull(gen.getConfigUpdate());
353 assertNull(gen.getConfigUrl());
354 assertEquals("sub", gen.getModulesPath());
355 assertNull(gen.getModulesUpdate());
356 assertEquals("git://example.com/sub", gen.getModulesUrl());
357 assertNull(gen.getRepository());
358 assertFalse(gen.next());
359 }
360
361 @Test
362 public void treeIdWithGitmodules() throws Exception {
363 final ObjectId subId = ObjectId
364 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
365 final String path = "sub";
366
367 final Config gitmodules = new Config();
368 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_PATH,
369 "sub");
370 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
371 "git://example.com/sub");
372
373 RevCommit commit = testDb.getRevWalk().parseCommit(testDb.commit()
374 .noParents()
375 .add(DOT_GIT_MODULES, gitmodules.toText())
376 .edit(new PathEdit(path) {
377
378 public void apply(DirCacheEntry ent) {
379 ent.setFileMode(FileMode.GITLINK);
380 ent.setObjectId(subId);
381 }
382 })
383 .create());
384
385 SubmoduleWalk gen = SubmoduleWalk.forPath(db, commit.getTree(), "sub");
386 assertEquals(path, gen.getPath());
387 assertEquals(subId, gen.getObjectId());
388 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
389 assertNull(gen.getConfigUpdate());
390 assertNull(gen.getConfigUrl());
391 assertEquals("sub", gen.getModulesPath());
392 assertNull(gen.getModulesUpdate());
393 assertEquals("git://example.com/sub", gen.getModulesUrl());
394 assertNull(gen.getRepository());
395 assertFalse(gen.next());
396 }
397
398 @Test
399 public void testTreeIteratorWithGitmodules() throws Exception {
400 final ObjectId subId = ObjectId
401 .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
402 final String path = "sub";
403
404 final Config gitmodules = new Config();
405 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_PATH,
406 "sub");
407 gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
408 "git://example.com/sub");
409
410 RevCommit commit = testDb.getRevWalk().parseCommit(testDb.commit()
411 .noParents()
412 .add(DOT_GIT_MODULES, gitmodules.toText())
413 .edit(new PathEdit(path) {
414
415 public void apply(DirCacheEntry ent) {
416 ent.setFileMode(FileMode.GITLINK);
417 ent.setObjectId(subId);
418 }
419 })
420 .create());
421
422 final CanonicalTreeParser p = new CanonicalTreeParser();
423 p.reset(testDb.getRevWalk().getObjectReader(), commit.getTree());
424 SubmoduleWalk gen = SubmoduleWalk.forPath(db, p, "sub");
425 assertEquals(path, gen.getPath());
426 assertEquals(subId, gen.getObjectId());
427 assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
428 assertNull(gen.getConfigUpdate());
429 assertNull(gen.getConfigUrl());
430 assertEquals("sub", gen.getModulesPath());
431 assertNull(gen.getModulesUpdate());
432 assertEquals("git://example.com/sub", gen.getModulesUrl());
433 assertNull(gen.getRepository());
434 assertFalse(gen.next());
435 }
436 }