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