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