View Javadoc
1   /*
2    * Copyright (C) 2011, GitHub Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  package org.eclipse.jgit.submodule;
44  
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.assertNotNull;
47  import static org.junit.Assert.assertNull;
48  import static org.junit.Assert.assertTrue;
49  import static org.junit.Assert.fail;
50  
51  import java.io.File;
52  import java.io.IOException;
53  import java.util.Collection;
54  
55  import org.eclipse.jgit.api.SubmoduleInitCommand;
56  import org.eclipse.jgit.api.errors.GitAPIException;
57  import org.eclipse.jgit.api.errors.JGitInternalException;
58  import org.eclipse.jgit.dircache.DirCache;
59  import org.eclipse.jgit.dircache.DirCacheEditor;
60  import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
61  import org.eclipse.jgit.dircache.DirCacheEntry;
62  import org.eclipse.jgit.errors.ConfigInvalidException;
63  import org.eclipse.jgit.junit.RepositoryTestCase;
64  import org.eclipse.jgit.lib.ConfigConstants;
65  import org.eclipse.jgit.lib.Constants;
66  import org.eclipse.jgit.lib.FileMode;
67  import org.eclipse.jgit.lib.ObjectId;
68  import org.eclipse.jgit.storage.file.FileBasedConfig;
69  import org.junit.Test;
70  
71  /**
72   * Unit tests of {@link SubmoduleInitCommand}
73   */
74  public class SubmoduleInitTest extends RepositoryTestCase {
75  
76  	@Test
77  	public void repositoryWithNoSubmodules() throws GitAPIException {
78  		SubmoduleInitCommand command = new SubmoduleInitCommand(db);
79  		Collection<String> modules = command.call();
80  		assertNotNull(modules);
81  		assertTrue(modules.isEmpty());
82  	}
83  
84  	@Test
85  	public void repositoryWithUninitializedModule() throws IOException,
86  			ConfigInvalidException, GitAPIException {
87  		final String path = addSubmoduleToIndex();
88  
89  		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
90  		assertTrue(generator.next());
91  		assertNull(generator.getConfigUrl());
92  		assertNull(generator.getConfigUpdate());
93  
94  		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
95  				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
96  		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
97  				ConfigConstants.CONFIG_KEY_PATH, path);
98  		String url = "git://server/repo.git";
99  		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
100 				ConfigConstants.CONFIG_KEY_URL, url);
101 		String update = "rebase";
102 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
103 				ConfigConstants.CONFIG_KEY_UPDATE, update);
104 		modulesConfig.save();
105 
106 		SubmoduleInitCommand command = new SubmoduleInitCommand(db);
107 		Collection<String> modules = command.call();
108 		assertNotNull(modules);
109 		assertEquals(1, modules.size());
110 		assertEquals(path, modules.iterator().next());
111 
112 		generator = SubmoduleWalk.forIndex(db);
113 		assertTrue(generator.next());
114 		assertEquals(url, generator.getConfigUrl());
115 		assertEquals(update, generator.getConfigUpdate());
116 	}
117 
118 	@Test
119 	public void resolveSameLevelRelativeUrl() throws Exception {
120 		final String path = addSubmoduleToIndex();
121 
122 		String base = "git://server/repo.git";
123 		FileBasedConfig config = db.getConfig();
124 		config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
125 				Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
126 				base);
127 		config.save();
128 
129 		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
130 		assertTrue(generator.next());
131 		assertNull(generator.getConfigUrl());
132 		assertNull(generator.getConfigUpdate());
133 
134 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
135 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
136 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
137 				ConfigConstants.CONFIG_KEY_PATH, path);
138 		String url = "./sub.git";
139 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
140 				ConfigConstants.CONFIG_KEY_URL, url);
141 		String update = "rebase";
142 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
143 				ConfigConstants.CONFIG_KEY_UPDATE, update);
144 		modulesConfig.save();
145 
146 		SubmoduleInitCommand command = new SubmoduleInitCommand(db);
147 		Collection<String> modules = command.call();
148 		assertNotNull(modules);
149 		assertEquals(1, modules.size());
150 		assertEquals(path, modules.iterator().next());
151 
152 		generator = SubmoduleWalk.forIndex(db);
153 		assertTrue(generator.next());
154 		assertEquals("git://server/repo.git/sub.git", generator.getConfigUrl());
155 		assertEquals(update, generator.getConfigUpdate());
156 	}
157 
158 	@Test
159 	public void resolveOneLevelHigherRelativeUrl() throws IOException,
160 			ConfigInvalidException, GitAPIException {
161 		final String path = addSubmoduleToIndex();
162 
163 		String base = "git://server/repo.git";
164 		FileBasedConfig config = db.getConfig();
165 		config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
166 				Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
167 				base);
168 		config.save();
169 
170 		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
171 		assertTrue(generator.next());
172 		assertNull(generator.getConfigUrl());
173 		assertNull(generator.getConfigUpdate());
174 
175 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
176 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
177 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
178 				ConfigConstants.CONFIG_KEY_PATH, path);
179 		String url = "../sub.git";
180 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
181 				ConfigConstants.CONFIG_KEY_URL, url);
182 		String update = "rebase";
183 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
184 				ConfigConstants.CONFIG_KEY_UPDATE, update);
185 		modulesConfig.save();
186 
187 		SubmoduleInitCommand command = new SubmoduleInitCommand(db);
188 		Collection<String> modules = command.call();
189 		assertNotNull(modules);
190 		assertEquals(1, modules.size());
191 		assertEquals(path, modules.iterator().next());
192 
193 		generator = SubmoduleWalk.forIndex(db);
194 		assertTrue(generator.next());
195 		assertEquals("git://server/sub.git", generator.getConfigUrl());
196 		assertEquals(update, generator.getConfigUpdate());
197 	}
198 
199 	@Test
200 	public void resolveTwoLevelHigherRelativeUrl() throws IOException,
201 			ConfigInvalidException, GitAPIException {
202 		final String path = addSubmoduleToIndex();
203 
204 		String base = "git://server/repo.git";
205 		FileBasedConfig config = db.getConfig();
206 		config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
207 				Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
208 				base);
209 		config.save();
210 
211 		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
212 		assertTrue(generator.next());
213 		assertNull(generator.getConfigUrl());
214 		assertNull(generator.getConfigUpdate());
215 
216 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
217 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
218 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
219 				ConfigConstants.CONFIG_KEY_PATH, path);
220 		String url = "../../server2/sub.git";
221 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
222 				ConfigConstants.CONFIG_KEY_URL, url);
223 		String update = "rebase";
224 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
225 				ConfigConstants.CONFIG_KEY_UPDATE, update);
226 		modulesConfig.save();
227 
228 		SubmoduleInitCommand command = new SubmoduleInitCommand(db);
229 		Collection<String> modules = command.call();
230 		assertNotNull(modules);
231 		assertEquals(1, modules.size());
232 		assertEquals(path, modules.iterator().next());
233 
234 		generator = SubmoduleWalk.forIndex(db);
235 		assertTrue(generator.next());
236 		assertEquals("git://server2/sub.git", generator.getConfigUrl());
237 		assertEquals(update, generator.getConfigUpdate());
238 	}
239 
240 	@Test
241 	public void resolveWorkingDirectoryRelativeUrl() throws IOException,
242 			GitAPIException, ConfigInvalidException {
243 		final String path = addSubmoduleToIndex();
244 
245 		String base = db.getWorkTree().getAbsolutePath();
246 		if (File.separatorChar == '\\')
247 			base = base.replace('\\', '/');
248 		FileBasedConfig config = db.getConfig();
249 		config.unset(ConfigConstants.CONFIG_REMOTE_SECTION,
250 				Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL);
251 		config.save();
252 
253 		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
254 		assertTrue(generator.next());
255 		assertNull(generator.getConfigUrl());
256 		assertNull(generator.getConfigUpdate());
257 
258 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
259 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
260 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
261 				ConfigConstants.CONFIG_KEY_PATH, path);
262 		String url = "./sub.git";
263 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
264 				ConfigConstants.CONFIG_KEY_URL, url);
265 		String update = "rebase";
266 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
267 				ConfigConstants.CONFIG_KEY_UPDATE, update);
268 		modulesConfig.save();
269 
270 		SubmoduleInitCommand command = new SubmoduleInitCommand(db);
271 		Collection<String> modules = command.call();
272 		assertNotNull(modules);
273 		assertEquals(1, modules.size());
274 		assertEquals(path, modules.iterator().next());
275 
276 		generator = SubmoduleWalk.forIndex(db);
277 		assertTrue(generator.next());
278 		assertEquals(base + "/sub.git", generator.getConfigUrl());
279 		assertEquals(update, generator.getConfigUpdate());
280 	}
281 
282 	@Test
283 	public void resolveInvalidParentUrl() throws IOException,
284 			ConfigInvalidException, GitAPIException {
285 		final String path = addSubmoduleToIndex();
286 
287 		String base = "no_slash";
288 		FileBasedConfig config = db.getConfig();
289 		config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
290 				Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
291 				base);
292 		config.save();
293 
294 		SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
295 		assertTrue(generator.next());
296 		assertNull(generator.getConfigUrl());
297 		assertNull(generator.getConfigUpdate());
298 
299 		FileBasedConfig modulesConfig = new FileBasedConfig(new File(
300 				db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
301 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
302 				ConfigConstants.CONFIG_KEY_PATH, path);
303 		String url = "../sub.git";
304 		modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
305 				ConfigConstants.CONFIG_KEY_URL, url);
306 		modulesConfig.save();
307 
308 		try {
309 			new SubmoduleInitCommand(db).call();
310 			fail("Exception not thrown");
311 		} catch (JGitInternalException e) {
312 			assertTrue(e.getCause() instanceof IOException);
313 		}
314 	}
315 
316 	private String addSubmoduleToIndex() throws IOException {
317 		final ObjectId id = ObjectId
318 				.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
319 		final String path = "sub";
320 		DirCache cache = db.lockDirCache();
321 		DirCacheEditor editor = cache.editor();
322 		editor.add(new PathEdit(path) {
323 
324 			@Override
325 			public void apply(DirCacheEntry ent) {
326 				ent.setFileMode(FileMode.GITLINK);
327 				ent.setObjectId(id);
328 			}
329 		});
330 		editor.commit();
331 		return path;
332 	}
333 }