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