View Javadoc
1   /*
2    * Copyright (C) 2011, GitHub Inc. 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.submodule;
11  
12  import static org.junit.Assert.assertEquals;
13  import static org.junit.Assert.assertNotNull;
14  import static org.junit.Assert.assertTrue;
15  
16  import java.io.File;
17  import java.io.IOException;
18  import java.util.Map;
19  import java.util.Map.Entry;
20  
21  import org.eclipse.jgit.api.Git;
22  import org.eclipse.jgit.api.SubmoduleStatusCommand;
23  import org.eclipse.jgit.api.errors.GitAPIException;
24  import org.eclipse.jgit.dircache.DirCache;
25  import org.eclipse.jgit.dircache.DirCacheEditor;
26  import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
27  import org.eclipse.jgit.dircache.DirCacheEntry;
28  import org.eclipse.jgit.junit.RepositoryTestCase;
29  import org.eclipse.jgit.junit.TestRepository;
30  import org.eclipse.jgit.lib.ConfigConstants;
31  import org.eclipse.jgit.lib.Constants;
32  import org.eclipse.jgit.lib.FileMode;
33  import org.eclipse.jgit.lib.ObjectId;
34  import org.eclipse.jgit.lib.Repository;
35  import org.eclipse.jgit.lib.StoredConfig;
36  import org.eclipse.jgit.storage.file.FileBasedConfig;
37  import org.junit.Test;
38  
39  /**
40   * Unit tests of {@link SubmoduleStatusCommand}
41   */
42  public class SubmoduleStatusTest extends RepositoryTestCase {
43  
44  	@Test
45  	public void repositoryWithNoSubmodules() throws GitAPIException {
46  		SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
47  		Map<String, SubmoduleStatus> statuses = command.call();
48  		assertNotNull(statuses);
49  		assertTrue(statuses.isEmpty());
50  	}
51  
52  	@Test
53  	public void repositoryWithMissingSubmodule() throws IOException,
54  			GitAPIException {
55  		final ObjectId id = ObjectId
56  				.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
57  		final String path = "sub";
58  		DirCache cache = db.lockDirCache();
59  		DirCacheEditor editor = cache.editor();
60  		editor.add(new PathEdit(path) {
61  
62  			@Override
63  			public void apply(DirCacheEntry ent) {
64  				ent.setFileMode(FileMode.GITLINK);
65  				ent.setObjectId(id);
66  			}
67  		});
68  		editor.commit();
69  
70  		SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
71  		Map<String, SubmoduleStatus> statuses = command.call();
72  		assertNotNull(statuses);
73  		assertEquals(1, statuses.size());
74  		Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator()
75  				.next();
76  		assertNotNull(module);
77  		assertEquals(path, module.getKey());
78  		SubmoduleStatus status = module.getValue();
79  		assertNotNull(status);
80  		assertEquals(path, status.getPath());
81  		assertEquals(id, status.getIndexId());
82  		assertEquals(SubmoduleStatusType.MISSING, status.getType());
83  	}
84  
85  	@Test
86  	public void repositoryWithUninitializedSubmodule() throws IOException,
87  			GitAPIException {
88  		final ObjectId id = ObjectId
89  				.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
90  		final String path = "sub";
91  		DirCache cache = db.lockDirCache();
92  		DirCacheEditor editor = cache.editor();
93  		editor.add(new PathEdit(path) {
94  
95  			@Override
96  			public void apply(DirCacheEntry ent) {
97  				ent.setFileMode(FileMode.GITLINK);
98  				ent.setObjectId(id);
99  			}
100 		});
101 		editor.commit();
102 
103 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
104 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
105 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
106 				ConfigConstants.CONFIG_KEY_PATH, path);
107 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
108 				ConfigConstants.CONFIG_KEY_URL, "git://server/repo.git");
109 		modulesConfig.save();
110 
111 		SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
112 		Map<String, SubmoduleStatus> statuses = command.call();
113 		assertNotNull(statuses);
114 		assertEquals(1, statuses.size());
115 		Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator()
116 				.next();
117 		assertNotNull(module);
118 		assertEquals(path, module.getKey());
119 		SubmoduleStatus status = module.getValue();
120 		assertNotNull(status);
121 		assertEquals(path, status.getPath());
122 		assertEquals(id, status.getIndexId());
123 		assertEquals(SubmoduleStatusType.UNINITIALIZED, status.getType());
124 	}
125 
126 	@Test
127 	public void repositoryWithNoHeadInSubmodule() throws IOException,
128 			GitAPIException {
129 		final ObjectId id = ObjectId
130 				.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
131 		final String path = "sub";
132 		DirCache cache = db.lockDirCache();
133 		DirCacheEditor editor = cache.editor();
134 		editor.add(new PathEdit(path) {
135 
136 			@Override
137 			public void apply(DirCacheEntry ent) {
138 				ent.setFileMode(FileMode.GITLINK);
139 				ent.setObjectId(id);
140 			}
141 		});
142 		editor.commit();
143 
144 		String url = "git://server/repo.git";
145 		StoredConfig config = db.getConfig();
146 		config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
147 				ConfigConstants.CONFIG_KEY_URL, url);
148 		config.save();
149 
150 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
151 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
152 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
153 				ConfigConstants.CONFIG_KEY_PATH, path);
154 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
155 				ConfigConstants.CONFIG_KEY_URL, url);
156 		modulesConfig.save();
157 
158 		Repository subRepo = Git.init().setBare(false)
159 				.setDirectory(new File(db.getWorkTree(), path)).call()
160 				.getRepository();
161 		assertNotNull(subRepo);
162 
163 		SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
164 		Map<String, SubmoduleStatus> statuses = command.call();
165 		assertNotNull(statuses);
166 		assertEquals(1, statuses.size());
167 		Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator()
168 				.next();
169 		assertNotNull(module);
170 		assertEquals(path, module.getKey());
171 		SubmoduleStatus status = module.getValue();
172 		assertNotNull(status);
173 		assertEquals(path, status.getPath());
174 		assertEquals(id, status.getIndexId());
175 		assertEquals(SubmoduleStatusType.UNINITIALIZED, status.getType());
176 	}
177 
178 	@Test
179 	public void repositoryWithNoSubmoduleRepository() throws IOException,
180 			GitAPIException {
181 		final ObjectId id = ObjectId
182 				.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
183 		final String path = "sub";
184 		DirCache cache = db.lockDirCache();
185 		DirCacheEditor editor = cache.editor();
186 		editor.add(new PathEdit(path) {
187 
188 			@Override
189 			public void apply(DirCacheEntry ent) {
190 				ent.setFileMode(FileMode.GITLINK);
191 				ent.setObjectId(id);
192 			}
193 		});
194 		editor.commit();
195 
196 		String url = "git://server/repo.git";
197 		StoredConfig config = db.getConfig();
198 		config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
199 				ConfigConstants.CONFIG_KEY_URL, url);
200 		config.save();
201 
202 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
203 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
204 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
205 				ConfigConstants.CONFIG_KEY_PATH, path);
206 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
207 				ConfigConstants.CONFIG_KEY_URL, url);
208 		modulesConfig.save();
209 
210 		SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
211 		Map<String, SubmoduleStatus> statuses = command.call();
212 		assertNotNull(statuses);
213 		assertEquals(1, statuses.size());
214 		Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator()
215 				.next();
216 		assertNotNull(module);
217 		assertEquals(path, module.getKey());
218 		SubmoduleStatus status = module.getValue();
219 		assertNotNull(status);
220 		assertEquals(path, status.getPath());
221 		assertEquals(id, status.getIndexId());
222 		assertEquals(SubmoduleStatusType.UNINITIALIZED, status.getType());
223 	}
224 
225 	@Test
226 	public void repositoryWithInitializedSubmodule() throws Exception {
227 		String path = "sub";
228 		Repository subRepo = Git.init().setBare(false)
229 				.setDirectory(new File(db.getWorkTree(), path)).call()
230 				.getRepository();
231 		assertNotNull(subRepo);
232 
233 		ObjectId id;
234 		try (TestRepository<?> subTr = new TestRepository<>(subRepo)) {
235 			id = subTr.branch(Constants.HEAD).commit().create().copy();
236 		}
237 
238 		DirCache cache = db.lockDirCache();
239 		DirCacheEditor editor = cache.editor();
240 		editor.add(new PathEdit(path) {
241 
242 			@Override
243 			public void apply(DirCacheEntry ent) {
244 				ent.setFileMode(FileMode.GITLINK);
245 				ent.setObjectId(id);
246 			}
247 		});
248 		editor.commit();
249 
250 		String url = "git://server/repo.git";
251 		StoredConfig config = db.getConfig();
252 		config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
253 				ConfigConstants.CONFIG_KEY_URL, url);
254 		config.save();
255 
256 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
257 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
258 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
259 				ConfigConstants.CONFIG_KEY_PATH, path);
260 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
261 				ConfigConstants.CONFIG_KEY_URL, url);
262 		modulesConfig.save();
263 
264 		SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
265 		Map<String, SubmoduleStatus> statuses = command.call();
266 		assertNotNull(statuses);
267 		assertEquals(1, statuses.size());
268 		Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator()
269 				.next();
270 		assertNotNull(module);
271 		assertEquals(path, module.getKey());
272 		SubmoduleStatus status = module.getValue();
273 		assertNotNull(status);
274 		assertEquals(path, status.getPath());
275 		assertEquals(id, status.getIndexId());
276 		assertEquals(SubmoduleStatusType.INITIALIZED, status.getType());
277 	}
278 
279 	@Test
280 	public void repositoryWithDifferentRevCheckedOutSubmodule() throws Exception {
281 		String path = "sub";
282 		Repository subRepo = Git.init().setBare(false)
283 				.setDirectory(new File(db.getWorkTree(), path)).call()
284 				.getRepository();
285 		assertNotNull(subRepo);
286 
287 		try (TestRepository<?> subTr = new TestRepository<>(subRepo)) {
288 			ObjectId id = subTr.branch(Constants.HEAD).commit().create().copy();
289 			DirCache cache = db.lockDirCache();
290 			DirCacheEditor editor = cache.editor();
291 			editor.add(new PathEdit(path) {
292 
293 				@Override
294 				public void apply(DirCacheEntry ent) {
295 					ent.setFileMode(FileMode.GITLINK);
296 					ent.setObjectId(id);
297 				}
298 			});
299 			editor.commit();
300 
301 			String url = "git://server/repo.git";
302 			StoredConfig config = db.getConfig();
303 			config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
304 					ConfigConstants.CONFIG_KEY_URL, url);
305 			config.save();
306 
307 			FileBasedConfig modulesConfig = new FileBasedConfig(
308 					new File(db.getWorkTree(), Constants.DOT_GIT_MODULES),
309 					db.getFS());
310 			modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
311 					path, ConfigConstants.CONFIG_KEY_PATH, path);
312 			modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
313 					path, ConfigConstants.CONFIG_KEY_URL, url);
314 			modulesConfig.save();
315 
316 			ObjectId newId = subTr.branch(Constants.HEAD).commit().create()
317 					.copy();
318 
319 			SubmoduleStatusCommand command = new SubmoduleStatusCommand(db);
320 			Map<String, SubmoduleStatus> statuses = command.call();
321 			assertNotNull(statuses);
322 			assertEquals(1, statuses.size());
323 			Entry<String, SubmoduleStatus> module = statuses.entrySet()
324 					.iterator().next();
325 			assertNotNull(module);
326 			assertEquals(path, module.getKey());
327 			SubmoduleStatus status = module.getValue();
328 			assertNotNull(status);
329 			assertEquals(path, status.getPath());
330 			assertEquals(id, status.getIndexId());
331 			assertEquals(newId, status.getHeadId());
332 			assertEquals(SubmoduleStatusType.REV_CHECKED_OUT, status.getType());
333 		}
334 	}
335 }