View Javadoc
1   /*
2    * Copyright (C) 2014, Google 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.gitrepo;
44  
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.assertFalse;
47  import static org.junit.Assert.assertTrue;
48  
49  import java.io.BufferedReader;
50  import java.io.File;
51  import java.io.FileReader;
52  
53  import org.eclipse.jgit.api.Git;
54  import org.eclipse.jgit.junit.JGitTestUtil;
55  import org.eclipse.jgit.junit.RepositoryTestCase;
56  import org.eclipse.jgit.lib.Constants;
57  import org.eclipse.jgit.lib.ObjectId;
58  import org.eclipse.jgit.lib.Repository;
59  import org.eclipse.jgit.storage.file.FileBasedConfig;
60  import org.eclipse.jgit.util.FS;
61  import org.junit.Test;
62  
63  public class RepoCommandTest extends RepositoryTestCase {
64  
65  	private static final String BRANCH = "branch";
66  	private static final String TAG = "release";
67  
68  	private Repository defaultDb;
69  	private Repository notDefaultDb;
70  	private Repository groupADb;
71  	private Repository groupBDb;
72  
73  	private String rootUri;
74  	private String defaultUri;
75  	private String notDefaultUri;
76  	private String groupAUri;
77  	private String groupBUri;
78  
79  	private ObjectId oldCommitId;
80  
81  	public void setUp() throws Exception {
82  		super.setUp();
83  
84  		defaultDb = createWorkRepository();
85  		Git git = new Git(defaultDb);
86  		JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "branch world");
87  		git.add().addFilepattern("hello.txt").call();
88  		oldCommitId = git.commit().setMessage("Initial commit").call().getId();
89  		git.checkout().setName(BRANCH).setCreateBranch(true).call();
90  		git.checkout().setName("master").call();
91  		git.tag().setName(TAG).call();
92  		JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "master world");
93  		git.add().addFilepattern("hello.txt").call();
94  		git.commit().setMessage("Second commit").call();
95  		addRepoToClose(defaultDb);
96  
97  		notDefaultDb = createWorkRepository();
98  		git = new Git(notDefaultDb);
99  		JGitTestUtil.writeTrashFile(notDefaultDb, "world.txt", "hello");
100 		git.add().addFilepattern("world.txt").call();
101 		git.commit().setMessage("Initial commit").call();
102 		addRepoToClose(notDefaultDb);
103 
104 		groupADb = createWorkRepository();
105 		git = new Git(groupADb);
106 		JGitTestUtil.writeTrashFile(groupADb, "a.txt", "world");
107 		git.add().addFilepattern("a.txt").call();
108 		git.commit().setMessage("Initial commit").call();
109 		addRepoToClose(groupADb);
110 
111 		groupBDb = createWorkRepository();
112 		git = new Git(groupBDb);
113 		JGitTestUtil.writeTrashFile(groupBDb, "b.txt", "world");
114 		git.add().addFilepattern("b.txt").call();
115 		git.commit().setMessage("Initial commit").call();
116 		addRepoToClose(groupBDb);
117 
118 		resolveRelativeUris();
119 	}
120 
121 	@Test
122 	public void testAddRepoManifest() throws Exception {
123 		StringBuilder xmlContent = new StringBuilder();
124 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
125 			.append("<manifest>")
126 			.append("<remote name=\"remote1\" fetch=\".\" />")
127 			.append("<default revision=\"master\" remote=\"remote1\" />")
128 			.append("<project path=\"foo\" name=\"")
129 			.append(defaultUri)
130 			.append("\" />")
131 			.append("</manifest>");
132 		writeTrashFile("manifest.xml", xmlContent.toString());
133 		RepoCommand command = new RepoCommand(db);
134 		command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml")
135 			.setURI(rootUri)
136 			.call();
137 		File hello = new File(db.getWorkTree(), "foo/hello.txt");
138 		assertTrue("submodule should be checked out", hello.exists());
139 		BufferedReader reader = new BufferedReader(new FileReader(hello));
140 		String content = reader.readLine();
141 		reader.close();
142 		assertEquals("submodule content should be as expected",
143 				"master world", content);
144 	}
145 
146 	@Test
147 	public void testRepoManifestGroups() throws Exception {
148 		StringBuilder xmlContent = new StringBuilder();
149 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
150 			.append("<manifest>")
151 			.append("<remote name=\"remote1\" fetch=\".\" />")
152 			.append("<default revision=\"master\" remote=\"remote1\" />")
153 			.append("<project path=\"foo\" name=\"")
154 			.append(defaultUri)
155 			.append("\" groups=\"a,test\" />")
156 			.append("<project path=\"bar\" name=\"")
157 			.append(notDefaultUri)
158 			.append("\" groups=\"notdefault\" />")
159 			.append("<project path=\"a\" name=\"")
160 			.append(groupAUri)
161 			.append("\" groups=\"a\" />")
162 			.append("<project path=\"b\" name=\"")
163 			.append(groupBUri)
164 			.append("\" groups=\"b\" />")
165 			.append("</manifest>");
166 
167 		// default should have foo, a & b
168 		Repository localDb = createWorkRepository();
169 		JGitTestUtil.writeTrashFile(
170 				localDb, "manifest.xml", xmlContent.toString());
171 		RepoCommand command = new RepoCommand(localDb);
172 		command
173 			.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
174 			.setURI(rootUri)
175 			.call();
176 		File file = new File(localDb.getWorkTree(), "foo/hello.txt");
177 		assertTrue("default should have foo", file.exists());
178 		file = new File(localDb.getWorkTree(), "bar/world.txt");
179 		assertFalse("default shouldn't have bar", file.exists());
180 		file = new File(localDb.getWorkTree(), "a/a.txt");
181 		assertTrue("default should have a", file.exists());
182 		file = new File(localDb.getWorkTree(), "b/b.txt");
183 		assertTrue("default should have b", file.exists());
184 
185 		// all,-a should have bar & b
186 		localDb = createWorkRepository();
187 		JGitTestUtil.writeTrashFile(
188 				localDb, "manifest.xml", xmlContent.toString());
189 		command = new RepoCommand(localDb);
190 		command
191 			.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
192 			.setURI(rootUri)
193 			.setGroups("all,-a")
194 			.call();
195 		file = new File(localDb.getWorkTree(), "foo/hello.txt");
196 		assertFalse("\"all,-a\" shouldn't have foo", file.exists());
197 		file = new File(localDb.getWorkTree(), "bar/world.txt");
198 		assertTrue("\"all,-a\" should have bar", file.exists());
199 		file = new File(localDb.getWorkTree(), "a/a.txt");
200 		assertFalse("\"all,-a\" shuoldn't have a", file.exists());
201 		file = new File(localDb.getWorkTree(), "b/b.txt");
202 		assertTrue("\"all,-a\" should have b", file.exists());
203 	}
204 
205 	@Test
206 	public void testRepoManifestCopyFile() throws Exception {
207 		Repository localDb = createWorkRepository();
208 		StringBuilder xmlContent = new StringBuilder();
209 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
210 			.append("<manifest>")
211 			.append("<remote name=\"remote1\" fetch=\".\" />")
212 			.append("<default revision=\"master\" remote=\"remote1\" />")
213 			.append("<project path=\"foo\" name=\"")
214 			.append(defaultUri)
215 			.append("\">")
216 			.append("<copyfile src=\"hello.txt\" dest=\"Hello\" />")
217 			.append("</project>")
218 			.append("</manifest>");
219 		JGitTestUtil.writeTrashFile(
220 				localDb, "manifest.xml", xmlContent.toString());
221 		RepoCommand command = new RepoCommand(localDb);
222 		command
223 			.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
224 			.setURI(rootUri)
225 			.call();
226 		// The original file should exist
227 		File hello = new File(localDb.getWorkTree(), "foo/hello.txt");
228 		assertTrue("The original file should exist", hello.exists());
229 		BufferedReader reader = new BufferedReader(new FileReader(hello));
230 		String content = reader.readLine();
231 		reader.close();
232 		assertEquals("The original file should have expected content",
233 				"master world", content);
234 		// The dest file should also exist
235 		hello = new File(localDb.getWorkTree(), "Hello");
236 		assertTrue("The destination file should exist", hello.exists());
237 		reader = new BufferedReader(new FileReader(hello));
238 		content = reader.readLine();
239 		reader.close();
240 		assertEquals("The destination file should have expected content",
241 				"master world", content);
242 	}
243 
244 	@Test
245 	public void testBareRepo() throws Exception {
246 		try (
247 				Repository remoteDb = createBareRepository();
248 				Repository tempDb = createWorkRepository()) {
249 			StringBuilder xmlContent = new StringBuilder();
250 			xmlContent
251 					.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
252 					.append("<manifest>")
253 					.append("<remote name=\"remote1\" fetch=\".\" />")
254 					.append("<default revision=\"master\" remote=\"remote1\" />")
255 					.append("<project path=\"foo\" name=\"").append(defaultUri)
256 					.append("\" />").append("</manifest>");
257 			JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
258 					xmlContent.toString());
259 			RepoCommand command = new RepoCommand(remoteDb);
260 			command.setPath(
261 					tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
262 					.setURI(rootUri).call();
263 			// Clone it
264 			File directory = createTempDirectory("testBareRepo");
265 			Repository localDb = Git.cloneRepository().setDirectory(directory)
266 					.setURI(remoteDb.getDirectory().toURI().toString()).call()
267 					.getRepository();
268 			// The .gitmodules file should exist
269 			File gitmodules = new File(localDb.getWorkTree(), ".gitmodules");
270 			assertTrue("The .gitmodules file should exist", gitmodules.exists());
271 			// The first line of .gitmodules file should be expected
272 			BufferedReader reader = new BufferedReader(new FileReader(
273 					gitmodules));
274 			String content = reader.readLine();
275 			reader.close();
276 			assertEquals(
277 					"The first line of .gitmodules file should be as expected",
278 					"[submodule \"foo\"]", content);
279 			// The gitlink should be the same as remote head sha1
280 			String gitlink = localDb.resolve(Constants.HEAD + ":foo").name();
281 			localDb.close();
282 			String remote = defaultDb.resolve(Constants.HEAD).name();
283 			assertEquals("The gitlink should be the same as remote head",
284 					remote, gitlink);
285 		}
286 	}
287 
288 	@Test
289 	public void testRevision() throws Exception {
290 		StringBuilder xmlContent = new StringBuilder();
291 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
292 			.append("<manifest>")
293 			.append("<remote name=\"remote1\" fetch=\".\" />")
294 			.append("<default revision=\"master\" remote=\"remote1\" />")
295 			.append("<project path=\"foo\" name=\"")
296 			.append(defaultUri)
297 			.append("\" revision=\"")
298 			.append(oldCommitId.name())
299 			.append("\" />")
300 			.append("</manifest>");
301 		writeTrashFile("manifest.xml", xmlContent.toString());
302 		RepoCommand command = new RepoCommand(db);
303 		command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml")
304 			.setURI(rootUri)
305 			.call();
306 		File hello = new File(db.getWorkTree(), "foo/hello.txt");
307 		BufferedReader reader = new BufferedReader(new FileReader(hello));
308 		String content = reader.readLine();
309 		reader.close();
310 		assertEquals("submodule content should be as expected",
311 				"branch world", content);
312 	}
313 
314 	@Test
315 	public void testRevisionBranch() throws Exception {
316 		StringBuilder xmlContent = new StringBuilder();
317 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
318 			.append("<manifest>")
319 			.append("<remote name=\"remote1\" fetch=\".\" />")
320 			.append("<default revision=\"")
321 			.append(BRANCH)
322 			.append("\" remote=\"remote1\" />")
323 			.append("<project path=\"foo\" name=\"")
324 			.append(defaultUri)
325 			.append("\" />")
326 			.append("</manifest>");
327 		writeTrashFile("manifest.xml", xmlContent.toString());
328 		RepoCommand command = new RepoCommand(db);
329 		command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml")
330 			.setURI(rootUri)
331 			.call();
332 		File hello = new File(db.getWorkTree(), "foo/hello.txt");
333 		BufferedReader reader = new BufferedReader(new FileReader(hello));
334 		String content = reader.readLine();
335 		reader.close();
336 		assertEquals("submodule content should be as expected",
337 				"branch world", content);
338 	}
339 
340 	@Test
341 	public void testRevisionTag() throws Exception {
342 		StringBuilder xmlContent = new StringBuilder();
343 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
344 			.append("<manifest>")
345 			.append("<remote name=\"remote1\" fetch=\".\" />")
346 			.append("<default revision=\"master\" remote=\"remote1\" />")
347 			.append("<project path=\"foo\" name=\"")
348 			.append(defaultUri)
349 			.append("\" revision=\"")
350 			.append(TAG)
351 			.append("\" />")
352 			.append("</manifest>");
353 		writeTrashFile("manifest.xml", xmlContent.toString());
354 		RepoCommand command = new RepoCommand(db);
355 		command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml")
356 			.setURI(rootUri)
357 			.call();
358 		File hello = new File(db.getWorkTree(), "foo/hello.txt");
359 		BufferedReader reader = new BufferedReader(new FileReader(hello));
360 		String content = reader.readLine();
361 		reader.close();
362 		assertEquals("submodule content should be as expected",
363 				"branch world", content);
364 	}
365 
366 	@Test
367 	public void testRevisionBare() throws Exception {
368 		try (
369 				Repository remoteDb = createBareRepository();
370 				Repository tempDb = createWorkRepository()) {
371 			StringBuilder xmlContent = new StringBuilder();
372 			xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
373 					.append("<manifest>")
374 					.append("<remote name=\"remote1\" fetch=\".\" />")
375 					.append("<default revision=\"").append(BRANCH)
376 					.append("\" remote=\"remote1\" />")
377 					.append("<project path=\"foo\" name=\"").append(defaultUri)
378 					.append("\" />").append("</manifest>");
379 			JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
380 					xmlContent.toString());
381 			RepoCommand command = new RepoCommand(remoteDb);
382 			command.setPath(
383 					tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
384 					.setURI(rootUri).call();
385 			// Clone it
386 			File directory = createTempDirectory("testRevisionBare");
387 			Repository localDb = Git.cloneRepository().setDirectory(directory)
388 					.setURI(remoteDb.getDirectory().toURI().toString()).call()
389 					.getRepository();
390 			// The gitlink should be the same as oldCommitId
391 			String gitlink = localDb.resolve(Constants.HEAD + ":foo").name();
392 			localDb.close();
393 			assertEquals("The gitlink is same as remote head",
394 					oldCommitId.name(), gitlink);
395 		}
396 	}
397 
398 	@Test
399 	public void testCopyFileBare() throws Exception {
400 		try (
401 				Repository remoteDb = createBareRepository();
402 				Repository tempDb = createWorkRepository()) {
403 			StringBuilder xmlContent = new StringBuilder();
404 			xmlContent
405 					.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
406 					.append("<manifest>")
407 					.append("<remote name=\"remote1\" fetch=\".\" />")
408 					.append("<default revision=\"master\" remote=\"remote1\" />")
409 					.append("<project path=\"foo\" name=\"").append(defaultUri)
410 					.append("\" revision=\"").append(BRANCH).append("\" >")
411 					.append("<copyfile src=\"hello.txt\" dest=\"Hello\" />")
412 					.append("<copyfile src=\"hello.txt\" dest=\"foo/Hello\" />")
413 					.append("</project>").append("</manifest>");
414 			JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
415 					xmlContent.toString());
416 			RepoCommand command = new RepoCommand(remoteDb);
417 			command.setPath(
418 					tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
419 					.setURI(rootUri).call();
420 			// Clone it
421 			File directory = createTempDirectory("testCopyFileBare");
422 			Repository localDb = Git.cloneRepository().setDirectory(directory)
423 					.setURI(remoteDb.getDirectory().toURI().toString()).call()
424 					.getRepository();
425 			// The Hello file should exist
426 			File hello = new File(localDb.getWorkTree(), "Hello");
427 			assertTrue("The Hello file should exist", hello.exists());
428 			// The foo/Hello file should be skipped.
429 			File foohello = new File(localDb.getWorkTree(), "foo/Hello");
430 			assertFalse(
431 					"The foo/Hello file should be skipped", foohello.exists());
432 			localDb.close();
433 			// The content of Hello file should be expected
434 			BufferedReader reader = new BufferedReader(new FileReader(hello));
435 			String content = reader.readLine();
436 			reader.close();
437 			assertEquals("The Hello file should have expected content",
438 					"branch world", content);
439 		}
440 	}
441 
442 	@Test
443 	public void testReplaceManifestBare() throws Exception {
444 		try (
445 				Repository remoteDb = createBareRepository();
446 				Repository tempDb = createWorkRepository()) {
447 			StringBuilder xmlContent = new StringBuilder();
448 			xmlContent
449 					.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
450 					.append("<manifest>")
451 					.append("<remote name=\"remote1\" fetch=\".\" />")
452 					.append("<default revision=\"master\" remote=\"remote1\" />")
453 					.append("<project path=\"foo\" name=\"").append(defaultUri)
454 					.append("\" revision=\"").append(BRANCH).append("\" >")
455 					.append("<copyfile src=\"hello.txt\" dest=\"Hello\" />")
456 					.append("</project>").append("</manifest>");
457 			JGitTestUtil.writeTrashFile(tempDb, "old.xml",
458 					xmlContent.toString());
459 			RepoCommand command = new RepoCommand(remoteDb);
460 			command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/old.xml")
461 					.setURI(rootUri).call();
462 			xmlContent = new StringBuilder();
463 			xmlContent
464 					.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
465 					.append("<manifest>")
466 					.append("<remote name=\"remote1\" fetch=\".\" />")
467 					.append("<default revision=\"master\" remote=\"remote1\" />")
468 					.append("<project path=\"bar\" name=\"")
469 					.append(defaultUri)
470 					.append("\" revision=\"")
471 					.append(BRANCH)
472 					.append("\" >")
473 					.append("<copyfile src=\"hello.txt\" dest=\"Hello.txt\" />")
474 					.append("</project>").append("</manifest>");
475 			JGitTestUtil.writeTrashFile(tempDb, "new.xml",
476 					xmlContent.toString());
477 			command = new RepoCommand(remoteDb);
478 			command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/new.xml")
479 					.setURI(rootUri).call();
480 			// Clone it
481 			File directory = createTempDirectory("testReplaceManifestBare");
482 			Repository localDb = Git.cloneRepository().setDirectory(directory)
483 					.setURI(remoteDb.getDirectory().toURI().toString()).call()
484 					.getRepository();
485 			// The Hello file should not exist
486 			File hello = new File(localDb.getWorkTree(), "Hello");
487 			assertFalse("The Hello file shouldn't exist", hello.exists());
488 			// The Hello.txt file should exist
489 			File hellotxt = new File(localDb.getWorkTree(), "Hello.txt");
490 			assertTrue("The Hello.txt file should exist", hellotxt.exists());
491 			// The .gitmodules file should have 'submodule "bar"' and shouldn't
492 			// have
493 			// 'submodule "foo"' lines.
494 			File dotmodules = new File(localDb.getWorkTree(),
495 					Constants.DOT_GIT_MODULES);
496 			localDb.close();
497 			BufferedReader reader = new BufferedReader(new FileReader(
498 					dotmodules));
499 			boolean foo = false;
500 			boolean bar = false;
501 			while (true) {
502 				String line = reader.readLine();
503 				if (line == null)
504 					break;
505 				if (line.contains("submodule \"foo\""))
506 					foo = true;
507 				if (line.contains("submodule \"bar\""))
508 					bar = true;
509 			}
510 			reader.close();
511 			assertTrue("The bar submodule should exist", bar);
512 			assertFalse("The foo submodule shouldn't exist", foo);
513 		}
514 	}
515 
516 	@Test
517 	public void testRemoveOverlappingBare() throws Exception {
518 		try (
519 				Repository remoteDb = createBareRepository();
520 				Repository tempDb = createWorkRepository()) {
521 			StringBuilder xmlContent = new StringBuilder();
522 			xmlContent
523 					.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
524 					.append("<manifest>")
525 					.append("<remote name=\"remote1\" fetch=\".\" />")
526 					.append("<default revision=\"master\" remote=\"remote1\" />")
527 					.append("<project path=\"foo/bar\" name=\"")
528 					.append(groupBUri).append("\" />")
529 					.append("<project path=\"a\" name=\"").append(groupAUri)
530 					.append("\" />").append("<project path=\"foo\" name=\"")
531 					.append(defaultUri).append("\" />").append("</manifest>");
532 			JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
533 					xmlContent.toString());
534 			RepoCommand command = new RepoCommand(remoteDb);
535 			command.setPath(
536 					tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
537 					.setURI(rootUri).call();
538 			// Clone it
539 			File directory = createTempDirectory("testRemoveOverlappingBare");
540 			Repository localDb = Git.cloneRepository().setDirectory(directory)
541 					.setURI(remoteDb.getDirectory().toURI().toString()).call()
542 					.getRepository();
543 			// The .gitmodules file should have 'submodule "foo"' and shouldn't
544 			// have
545 			// 'submodule "foo/bar"' lines.
546 			File dotmodules = new File(localDb.getWorkTree(),
547 					Constants.DOT_GIT_MODULES);
548 			localDb.close();
549 			BufferedReader reader = new BufferedReader(new FileReader(
550 					dotmodules));
551 			boolean foo = false;
552 			boolean foobar = false;
553 			boolean a = false;
554 			while (true) {
555 				String line = reader.readLine();
556 				if (line == null)
557 					break;
558 				if (line.contains("submodule \"foo\""))
559 					foo = true;
560 				if (line.contains("submodule \"foo/bar\""))
561 					foobar = true;
562 				if (line.contains("submodule \"a\""))
563 					a = true;
564 			}
565 			reader.close();
566 			assertTrue("The foo submodule should exist", foo);
567 			assertFalse("The foo/bar submodule shouldn't exist", foobar);
568 			assertTrue("The a submodule should exist", a);
569 		}
570 	}
571 
572 	@Test
573 	public void testIncludeTag() throws Exception {
574 		Repository localDb = createWorkRepository();
575 		Repository tempDb = createWorkRepository();
576 
577 		StringBuilder xmlContent = new StringBuilder();
578 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
579 			.append("<manifest>")
580 			.append("<include name=\"_include.xml\" />")
581 			.append("<default revision=\"master\" remote=\"remote1\" />")
582 			.append("</manifest>");
583 		JGitTestUtil.writeTrashFile(
584 				tempDb, "manifest.xml", xmlContent.toString());
585 
586 		xmlContent = new StringBuilder();
587 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
588 			.append("<manifest>")
589 			.append("<remote name=\"remote1\" fetch=\".\" />")
590 			.append("<default revision=\"master\" remote=\"remote1\" />")
591 			.append("<project path=\"foo\" name=\"")
592 			.append(defaultUri)
593 			.append("\" />")
594 			.append("</manifest>");
595 		JGitTestUtil.writeTrashFile(
596 				tempDb, "_include.xml", xmlContent.toString());
597 
598 		RepoCommand command = new RepoCommand(localDb);
599 		command
600 			.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
601 			.setURI(rootUri)
602 			.call();
603 		File hello = new File(localDb.getWorkTree(), "foo/hello.txt");
604 		assertTrue("submodule should be checked out", hello.exists());
605 		BufferedReader reader = new BufferedReader(new FileReader(hello));
606 		String content = reader.readLine();
607 		reader.close();
608 		assertEquals("submodule content should be as expected",
609 				"master world", content);
610 	}
611 
612 	@Test
613 	public void testNonDefaultRemotes() throws Exception {
614 		StringBuilder xmlContent = new StringBuilder();
615 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
616 			.append("<manifest>")
617 			.append("<remote name=\"remote1\" fetch=\".\" />")
618 			.append("<remote name=\"remote2\" fetch=\"")
619 			.append(notDefaultUri)
620 			.append("\" />")
621 			.append("<default revision=\"master\" remote=\"remote1\" />")
622 			.append("<project path=\"foo\" name=\"")
623 			.append(defaultUri)
624 			.append("\" />")
625 			.append("<project path=\"bar\" name=\".\" remote=\"remote2\" />")
626 			.append("</manifest>");
627 
628 		Repository localDb = createWorkRepository();
629 		JGitTestUtil.writeTrashFile(
630 				localDb, "manifest.xml", xmlContent.toString());
631 		RepoCommand command = new RepoCommand(localDb);
632 		command
633 			.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
634 			.setURI(rootUri)
635 			.call();
636 		File file = new File(localDb.getWorkTree(), "foo/hello.txt");
637 		assertTrue("We should have foo", file.exists());
638 		file = new File(localDb.getWorkTree(), "bar/world.txt");
639 		assertTrue("We should have bar", file.exists());
640 	}
641 
642 	@Test
643 	public void testRemoteAlias() throws Exception {
644 		StringBuilder xmlContent = new StringBuilder();
645 		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
646 			.append("<manifest>")
647 			.append("<remote name=\"remote1\" fetch=\".\" alias=\"remote2\" />")
648 			.append("<default revision=\"master\" remote=\"remote2\" />")
649 			.append("<project path=\"foo\" name=\"")
650 			.append(defaultUri)
651 			.append("\" />")
652 			.append("</manifest>");
653 
654 		Repository localDb = createWorkRepository();
655 		JGitTestUtil.writeTrashFile(
656 				localDb, "manifest.xml", xmlContent.toString());
657 		RepoCommand command = new RepoCommand(localDb);
658 		command
659 			.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
660 			.setURI(rootUri)
661 			.call();
662 		File file = new File(localDb.getWorkTree(), "foo/hello.txt");
663 		assertTrue("We should have foo", file.exists());
664 	}
665 
666 	@Test
667 	public void testTargetBranch() throws Exception {
668 		try (
669 				Repository remoteDb1 = createBareRepository();
670 				Repository remoteDb2 = createBareRepository();
671 				Repository tempDb = createWorkRepository()) {
672 			StringBuilder xmlContent = new StringBuilder();
673 			xmlContent
674 					.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
675 					.append("<manifest>")
676 					.append("<remote name=\"remote1\" fetch=\".\" />")
677 					.append("<default revision=\"master\" remote=\"remote1\" />")
678 					.append("<project path=\"foo\" name=\"").append(defaultUri)
679 					.append("\" />").append("</manifest>");
680 			JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
681 					xmlContent.toString());
682 			RepoCommand command = new RepoCommand(remoteDb1);
683 			command
684 				.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
685 				.setURI(rootUri)
686 				.setTargetBranch("test")
687 				.call();
688 			ObjectId branchId = remoteDb1.resolve(
689 					Constants.R_HEADS + "test^{tree}");
690 			command = new RepoCommand(remoteDb2);
691 			command
692 				.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
693 				.setURI(rootUri)
694 				.call();
695 			ObjectId defaultId = remoteDb2.resolve(Constants.HEAD + "^{tree}");
696 			assertEquals(
697 				"The tree id of branch db and default db should be the same",
698 				branchId, defaultId);
699 		}
700 	}
701 
702 	@Test
703 	public void testRecordRemoteBranch() throws Exception {
704 		try (
705 				Repository remoteDb = createBareRepository();
706 				Repository tempDb = createWorkRepository()) {
707 			StringBuilder xmlContent = new StringBuilder();
708 			xmlContent
709 				.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
710 				.append("<manifest>")
711 				.append("<remote name=\"remote1\" fetch=\".\" />")
712 				.append("<default revision=\"master\" remote=\"remote1\" />")
713 				.append("<project path=\"with-branch\" ")
714 					.append("revision=\"master\" ")
715 					.append("name=\"").append(notDefaultUri).append("\" />")
716 				.append("<project path=\"with-long-branch\" ")
717 					.append("revision=\"refs/heads/master\" ")
718 					.append("name=\"").append(defaultUri).append("\" />")
719 				.append("</manifest>");
720 			JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
721 				xmlContent.toString());
722 
723 			RepoCommand command = new RepoCommand(remoteDb);
724 			command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
725 				.setURI(rootUri)
726 				.setRecordRemoteBranch(true)
727 				.call();
728 			// Clone it
729 			File directory = createTempDirectory("testBareRepo");
730 			try (Repository localDb = Git.cloneRepository()
731 					.setDirectory(directory)
732 					.setURI(remoteDb.getDirectory().toURI().toString()).call()
733 					.getRepository();) {
734 				// The .gitmodules file should exist
735 				File gitmodules = new File(localDb.getWorkTree(),
736 						".gitmodules");
737 				assertTrue("The .gitmodules file should exist",
738 						gitmodules.exists());
739 				FileBasedConfig c = new FileBasedConfig(gitmodules,
740 						FS.DETECTED);
741 				c.load();
742 				assertEquals("standard branches work", "master",
743 						c.getString("submodule", "with-branch", "branch"));
744 				assertEquals("long branches work", "refs/heads/master",
745 						c.getString("submodule", "with-long-branch", "branch"));
746 			}
747 		}
748 	}
749 
750 	private void resolveRelativeUris() {
751 		// Find the longest common prefix ends with "/" as rootUri.
752 		defaultUri = defaultDb.getDirectory().toURI().toString();
753 		notDefaultUri = notDefaultDb.getDirectory().toURI().toString();
754 		groupAUri = groupADb.getDirectory().toURI().toString();
755 		groupBUri = groupBDb.getDirectory().toURI().toString();
756 		int start = 0;
757 		while (start <= defaultUri.length()) {
758 			int newStart = defaultUri.indexOf('/', start + 1);
759 			String prefix = defaultUri.substring(0, newStart);
760 			if (!notDefaultUri.startsWith(prefix) ||
761 					!groupAUri.startsWith(prefix) ||
762 					!groupBUri.startsWith(prefix)) {
763 				start++;
764 				rootUri = defaultUri.substring(0, start) + "manifest";
765 				defaultUri = defaultUri.substring(start);
766 				notDefaultUri = notDefaultUri.substring(start);
767 				groupAUri = groupAUri.substring(start);
768 				groupBUri = groupBUri.substring(start);
769 				return;
770 			}
771 			start = newStart;
772 		}
773 	}
774 }