View Javadoc
1   /*
2    * Copyright (C) 2011, 2022 Chris Aniszczyk <caniszczyk@gmail.com> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.api;
11  
12  import static org.junit.Assert.assertArrayEquals;
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertFalse;
15  import static org.junit.Assert.assertNotEquals;
16  import static org.junit.Assert.assertNotNull;
17  import static org.junit.Assert.assertNull;
18  import static org.junit.Assert.assertTrue;
19  import static org.junit.Assert.fail;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.net.URISyntaxException;
24  import java.time.Instant;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.stream.Collectors;
30  import java.util.stream.Stream;
31  import java.util.stream.StreamSupport;
32  
33  import org.eclipse.jgit.api.ListBranchCommand.ListMode;
34  import org.eclipse.jgit.api.errors.GitAPIException;
35  import org.eclipse.jgit.api.errors.JGitInternalException;
36  import org.eclipse.jgit.errors.NoWorkTreeException;
37  import org.eclipse.jgit.junit.RepositoryTestCase;
38  import org.eclipse.jgit.junit.TestRepository;
39  import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
40  import org.eclipse.jgit.lib.ConfigConstants;
41  import org.eclipse.jgit.lib.Constants;
42  import org.eclipse.jgit.lib.ObjectId;
43  import org.eclipse.jgit.lib.Ref;
44  import org.eclipse.jgit.lib.RefUpdate;
45  import org.eclipse.jgit.lib.Repository;
46  import org.eclipse.jgit.lib.StoredConfig;
47  import org.eclipse.jgit.revwalk.RevBlob;
48  import org.eclipse.jgit.revwalk.RevCommit;
49  import org.eclipse.jgit.revwalk.RevObject;
50  import org.eclipse.jgit.submodule.SubmoduleStatus;
51  import org.eclipse.jgit.submodule.SubmoduleStatusType;
52  import org.eclipse.jgit.submodule.SubmoduleWalk;
53  import org.eclipse.jgit.transport.RefSpec;
54  import org.eclipse.jgit.transport.RemoteConfig;
55  import org.eclipse.jgit.transport.TagOpt;
56  import org.eclipse.jgit.transport.URIish;
57  import org.eclipse.jgit.util.SystemReader;
58  import org.junit.Test;
59  
60  public class CloneCommandTest extends RepositoryTestCase {
61  
62  	private Git git;
63  
64  	private TestRepository<Repository> tr;
65  
66  	@Override
67  	public void setUp() throws Exception {
68  		super.setUp();
69  		tr = new TestRepository<>(db);
70  
71  		git = new Git(db);
72  		// commit something
73  		writeTrashFile("Test.txt", "Hello world");
74  		git.add().addFilepattern("Test.txt").call();
75  		git.commit().setMessage("Initial commit").call();
76  		Ref head = git.tag().setName("tag-initial").setMessage("Tag initial")
77  				.call();
78  
79  		// create a test branch and switch to it
80  		git.checkout().setCreateBranch(true).setName("test").call();
81  		// create a non-standard ref
82  		RefUpdate ru = db.updateRef("refs/meta/foo/bar");
83  		ru.setNewObjectId(head.getObjectId());
84  		ru.update();
85  
86  		// commit something on the test branch
87  		writeTrashFile("Test.txt", "Some change");
88  		git.add().addFilepattern("Test.txt").call();
89  		git.commit().setMessage("Second commit").call();
90  		RevBlob blob = tr.blob("blob-not-in-master-branch");
91  		git.tag().setName("tag-for-blob").setObjectId(blob).call();
92  	}
93  
94  	@Test
95  	public void testCloneRepository() throws IOException,
96  			JGitInternalException, GitAPIException, URISyntaxException {
97  		File directory = createTempDirectory("testCloneRepository");
98  		CloneCommand command = Git.cloneRepository();
99  		command.setDirectory(directory);
100 		command.setURI(fileUri());
101 		Git git2 = command.call();
102 		addRepoToClose(git2.getRepository());
103 		ObjectId id = git2.getRepository().resolve("tag-for-blob");
104 		assertNotNull(id);
105 		assertEquals(git2.getRepository().getFullBranch(), "refs/heads/test");
106 		assertEquals(
107 				"origin",
108 				git2.getRepository()
109 						.getConfig()
110 						.getString(ConfigConstants.CONFIG_BRANCH_SECTION,
111 								"test", ConfigConstants.CONFIG_KEY_REMOTE));
112 		assertEquals(
113 				"refs/heads/test",
114 				git2.getRepository()
115 						.getConfig()
116 						.getString(ConfigConstants.CONFIG_BRANCH_SECTION,
117 								"test", ConfigConstants.CONFIG_KEY_MERGE));
118 		assertEquals(2, git2.branchList().setListMode(ListMode.REMOTE).call()
119 				.size());
120 		assertEquals(new RefSpec("+refs/heads/*:refs/remotes/origin/*"),
121 				fetchRefSpec(git2.getRepository()));
122 		assertTagOption(git2.getRepository(), TagOpt.AUTO_FOLLOW);
123 	}
124 
125 	@Test
126 	public void testCloneRepositoryNoCheckout()
127 			throws IOException, JGitInternalException, GitAPIException {
128 		File directory = createTempDirectory("testCloneRepositoryNoCheckout");
129 		CloneCommand command = Git.cloneRepository();
130 		command.setDirectory(directory);
131 		command.setURI(fileUri());
132 		command.setNoCheckout(true);
133 		try (Git git2 = command.call()) {
134 			Repository clonedRepo = git2.getRepository();
135 			Ref main = clonedRepo.exactRef(Constants.R_HEADS + "test");
136 			assertNotNull(main);
137 			ObjectId id = main.getObjectId();
138 			assertNotNull(id);
139 			assertNotEquals(id, ObjectId.zeroId());
140 			ObjectId headId = clonedRepo.resolve(Constants.HEAD);
141 			assertEquals(id, headId);
142 			assertArrayEquals(new String[] { Constants.DOT_GIT },
143 					directory.list());
144 		}
145 	}
146 
147 	@Test
148 	public void testCloneRepositoryRefLogForLocalRefs()
149 			throws IOException, JGitInternalException, GitAPIException {
150 		File directory = createTempDirectory(
151 				"testCloneRepositoryRefLogForLocalRefs");
152 		CloneCommand command = Git.cloneRepository();
153 		command.setDirectory(directory);
154 		command.setURI(fileUri());
155 		Git git2 = command.call();
156 		Repository clonedRepo = git2.getRepository();
157 		addRepoToClose(clonedRepo);
158 
159 		List<Ref> clonedRefs = clonedRepo.getRefDatabase().getRefs();
160 		Stream<Ref> remoteRefs = clonedRefs.stream()
161 				.filter(CloneCommandTest::isRemote);
162 		Stream<Ref> localHeadsRefs = clonedRefs.stream()
163 				.filter(CloneCommandTest::isLocalHead);
164 
165 		remoteRefs.forEach(ref -> assertFalse(
166 				"Ref " + ref.getName()
167 						+ " is remote and should not have a reflog",
168 				hasRefLog(clonedRepo, ref)));
169 		localHeadsRefs.forEach(ref -> assertTrue(
170 				"Ref " + ref.getName()
171 						+ " is local head and should have a reflog",
172 				hasRefLog(clonedRepo, ref)));
173 	}
174 
175 	private static boolean isRemote(Ref ref) {
176 		return ref.getName().startsWith(Constants.R_REMOTES);
177 	}
178 
179 	private static boolean isLocalHead(Ref ref) {
180 		return !isRemote(ref) && ref.getName().startsWith(Constants.R_HEADS);
181 	}
182 
183 	private static boolean hasRefLog(Repository repo, Ref ref) {
184 		try {
185 			return repo.getReflogReader(ref.getName()).getLastEntry() != null;
186 		} catch (IOException ioe) {
187 			throw new IllegalStateException(ioe);
188 		}
189 	}
190 
191 	@Test
192 	public void testCloneRepositoryExplicitGitDir() throws IOException,
193 			JGitInternalException, GitAPIException {
194 		File directory = createTempDirectory("testCloneRepository");
195 		CloneCommand command = Git.cloneRepository();
196 		command.setDirectory(directory);
197 		command.setGitDir(new File(directory, Constants.DOT_GIT));
198 		command.setURI(fileUri());
199 		Git git2 = command.call();
200 		addRepoToClose(git2.getRepository());
201 		assertEquals(directory, git2.getRepository().getWorkTree());
202 		assertEquals(new File(directory, Constants.DOT_GIT), git2.getRepository()
203 				.getDirectory());
204 	}
205 
206 	@Test
207 	public void testCloneRepositoryDefaultDirectory()
208 			throws URISyntaxException, JGitInternalException {
209 		CloneCommand command = Git.cloneRepository().setURI(fileUri());
210 
211 		command.verifyDirectories(new URIish(fileUri()));
212 		File directory = command.getDirectory();
213 		assertEquals(git.getRepository().getWorkTree().getName(), directory.getName());
214 	}
215 
216 	@Test
217 	public void testCloneBareRepositoryDefaultDirectory()
218 			throws URISyntaxException, JGitInternalException {
219 		CloneCommand command = Git.cloneRepository().setURI(fileUri()).setBare(true);
220 
221 		command.verifyDirectories(new URIish(fileUri()));
222 		File directory = command.getDirectory();
223 		assertEquals(git.getRepository().getWorkTree().getName() + Constants.DOT_GIT_EXT, directory.getName());
224 	}
225 
226 	@Test
227 	public void testCloneRepositoryExplicitGitDirNonStd() throws IOException,
228 			JGitInternalException, GitAPIException {
229 		File directory = createTempDirectory("testCloneRepository");
230 		File gDir = createTempDirectory("testCloneRepository.git");
231 		CloneCommand command = Git.cloneRepository();
232 		command.setDirectory(directory);
233 		command.setGitDir(gDir);
234 		command.setURI(fileUri());
235 		Git git2 = command.call();
236 		addRepoToClose(git2.getRepository());
237 		assertEquals(directory, git2.getRepository().getWorkTree());
238 		assertEquals(gDir, git2.getRepository()
239 				.getDirectory());
240 		assertTrue(new File(directory, Constants.DOT_GIT).isFile());
241 		assertFalse(new File(gDir, Constants.DOT_GIT).exists());
242 	}
243 
244 	@Test
245 	public void testCloneRepositoryExplicitGitDirBare() throws IOException,
246 			JGitInternalException, GitAPIException {
247 		File gDir = createTempDirectory("testCloneRepository.git");
248 		CloneCommand command = Git.cloneRepository();
249 		command.setBare(true);
250 		command.setGitDir(gDir);
251 		command.setURI(fileUri());
252 		Git git2 = command.call();
253 		addRepoToClose(git2.getRepository());
254 		try {
255 			assertNull(null, git2.getRepository().getWorkTree());
256 			fail("Expected NoWorkTreeException");
257 		} catch (NoWorkTreeException e) {
258 			assertEquals(gDir, git2.getRepository().getDirectory());
259 		}
260 	}
261 
262 	@Test
263 	public void testBareCloneRepository() throws IOException,
264 			JGitInternalException, GitAPIException, URISyntaxException {
265 		File directory = createTempDirectory("testCloneRepository_bare");
266 		CloneCommand command = Git.cloneRepository();
267 		command.setBare(true);
268 		command.setDirectory(directory);
269 		command.setURI(fileUri());
270 		Git git2 = command.call();
271 		addRepoToClose(git2.getRepository());
272 		assertEquals(new RefSpec("+refs/heads/*:refs/heads/*"),
273 				fetchRefSpec(git2.getRepository()));
274 	}
275 
276 	@Test
277 	public void testCloneRepositoryCustomRemote() throws Exception {
278 		File directory = createTempDirectory("testCloneRemoteUpstream");
279 		CloneCommand command = Git.cloneRepository();
280 		command.setDirectory(directory);
281 		command.setRemote("upstream");
282 		command.setURI(fileUri());
283 		Git git2 = command.call();
284 		addRepoToClose(git2.getRepository());
285 		assertEquals("+refs/heads/*:refs/remotes/upstream/*",
286 				git2.getRepository()
287 					.getConfig()
288 					.getStringList("remote", "upstream",
289 							"fetch")[0]);
290 		assertEquals("upstream",
291 				git2.getRepository()
292 					.getConfig()
293 					.getString("branch", "test", "remote"));
294 		assertEquals(db.resolve("test"),
295 				git2.getRepository().resolve("upstream/test"));
296 	}
297 
298 	@Test
299 	public void testBareCloneRepositoryCustomRemote() throws Exception {
300 		File directory = createTempDirectory("testCloneRemoteUpstream_bare");
301 		CloneCommand command = Git.cloneRepository();
302 		command.setBare(true);
303 		command.setDirectory(directory);
304 		command.setRemote("upstream");
305 		command.setURI(fileUri());
306 		Git git2 = command.call();
307 		addRepoToClose(git2.getRepository());
308 		assertEquals("+refs/heads/*:refs/heads/*",
309 				git2.getRepository()
310 					.getConfig()
311 					.getStringList("remote", "upstream",
312 							"fetch")[0]);
313 		assertEquals("upstream",
314 				git2.getRepository()
315 					.getConfig()
316 					.getString("branch", "test", "remote"));
317 		assertNull(git2.getRepository().resolve("upstream/test"));
318 	}
319 
320 	@Test
321 	public void testBareCloneRepositoryNullRemote() throws Exception {
322 		File directory = createTempDirectory("testCloneRemoteNull_bare");
323 		CloneCommand command = Git.cloneRepository();
324 		command.setBare(true);
325 		command.setDirectory(directory);
326 		command.setRemote(null);
327 		command.setURI(fileUri());
328 		Git git2 = command.call();
329 		addRepoToClose(git2.getRepository());
330 		assertEquals("+refs/heads/*:refs/heads/*", git2.getRepository()
331 				.getConfig().getStringList("remote", "origin", "fetch")[0]);
332 		assertEquals("origin", git2.getRepository().getConfig()
333 				.getString("branch", "test", "remote"));
334 	}
335 
336 	public static RefSpec fetchRefSpec(Repository r) throws URISyntaxException {
337 		RemoteConfig remoteConfig =
338 				new RemoteConfig(r.getConfig(), Constants.DEFAULT_REMOTE_NAME);
339 		return remoteConfig.getFetchRefSpecs().get(0);
340 	}
341 
342 	@Test
343 	public void testCloneRepositoryWithBranch() throws IOException,
344 			JGitInternalException, GitAPIException {
345 		File directory = createTempDirectory("testCloneRepositoryWithBranch");
346 		CloneCommand command = Git.cloneRepository();
347 		command.setBranch("refs/heads/master");
348 		command.setDirectory(directory);
349 		command.setURI(fileUri());
350 		Git git2 = command.call();
351 		addRepoToClose(git2.getRepository());
352 
353 		assertEquals("refs/heads/master", git2.getRepository().getFullBranch());
354 		assertEquals(
355 				"refs/heads/master, refs/remotes/origin/master, refs/remotes/origin/test",
356 				allRefNames(git2.branchList().setListMode(ListMode.ALL).call()));
357 
358 		// Same thing, but now without checkout
359 		directory = createTempDirectory(
360 				"testCloneRepositoryWithBranch_noCheckout");
361 		command = Git.cloneRepository();
362 		command.setBranch("refs/heads/master");
363 		command.setDirectory(directory);
364 		command.setURI(fileUri());
365 		command.setNoCheckout(true);
366 		git2 = command.call();
367 		addRepoToClose(git2.getRepository());
368 
369 		assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
370 		assertEquals(
371 				"refs/heads/master, refs/remotes/origin/master, refs/remotes/origin/test",
372 				allRefNames(git2.branchList().setListMode(ListMode.ALL).call()));
373 
374 		// Same thing, but now test with bare repo
375 		directory = createTempDirectory("testCloneRepositoryWithBranch_bare");
376 		command = Git.cloneRepository();
377 		command.setBranch("refs/heads/master");
378 		command.setDirectory(directory);
379 		command.setURI(fileUri());
380 		command.setBare(true);
381 		git2 = command.call();
382 		addRepoToClose(git2.getRepository());
383 
384 		assertEquals("refs/heads/master", git2.getRepository().getFullBranch());
385 		assertEquals("refs/heads/master, refs/heads/test", allRefNames(git2
386 				.branchList().setListMode(ListMode.ALL).call()));
387 	}
388 
389 	@Test
390 	public void testCloneRepositoryWithBranchShortName() throws Exception {
391 		File directory = createTempDirectory("testCloneRepositoryWithBranch");
392 		CloneCommand command = Git.cloneRepository();
393 		command.setBranch("test");
394 		command.setDirectory(directory);
395 		command.setURI(fileUri());
396 		Git git2 = command.call();
397 		addRepoToClose(git2.getRepository());
398 
399 		assertEquals("refs/heads/test", git2.getRepository().getFullBranch());
400 	}
401 
402 	@Test
403 	public void testCloneRepositoryWithTagName() throws Exception {
404 		File directory = createTempDirectory("testCloneRepositoryWithBranch");
405 		CloneCommand command = Git.cloneRepository();
406 		command.setBranch("tag-initial");
407 		command.setDirectory(directory);
408 		command.setURI(fileUri());
409 		Git git2 = command.call();
410 		addRepoToClose(git2.getRepository());
411 
412 		ObjectId taggedCommit = db.resolve("tag-initial^{commit}");
413 		assertEquals(taggedCommit.name(), git2
414 				.getRepository().getFullBranch());
415 	}
416 
417 	@Test
418 	public void testCloneRepositoryOnlyOneBranch() throws Exception {
419 		File directory = createTempDirectory("testCloneRepositoryWithBranch");
420 		CloneCommand command = Git.cloneRepository();
421 		command.setBranch("refs/heads/master");
422 		command.setBranchesToClone(Collections
423 				.singletonList("refs/heads/master"));
424 		command.setDirectory(directory);
425 		command.setURI(fileUri());
426 		Git git2 = command.call();
427 		addRepoToClose(git2.getRepository());
428 		assertNull(git2.getRepository().resolve("tag-for-blob"));
429 		assertNotNull(git2.getRepository().resolve("tag-initial"));
430 		assertEquals("refs/heads/master", git2.getRepository().getFullBranch());
431 		assertEquals("refs/remotes/origin/master", allRefNames(git2
432 				.branchList().setListMode(ListMode.REMOTE).call()));
433 		RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
434 				Constants.DEFAULT_REMOTE_NAME);
435 		List<RefSpec> specs = cfg.getFetchRefSpecs();
436 		assertEquals(1, specs.size());
437 		assertEquals(
438 				new RefSpec("+refs/heads/master:refs/remotes/origin/master"),
439 				specs.get(0));
440 	}
441 
442 	@Test
443 	public void testBareCloneRepositoryOnlyOneBranch() throws Exception {
444 		File directory = createTempDirectory(
445 				"testCloneRepositoryWithBranch_bare");
446 		CloneCommand command = Git.cloneRepository();
447 		command.setBranch("refs/heads/master");
448 		command.setBranchesToClone(Collections
449 				.singletonList("refs/heads/master"));
450 		command.setDirectory(directory);
451 		command.setURI(fileUri());
452 		command.setBare(true);
453 		Git git2 = command.call();
454 		addRepoToClose(git2.getRepository());
455 		assertNull(git2.getRepository().resolve("tag-for-blob"));
456 		assertNotNull(git2.getRepository().resolve("tag-initial"));
457 		assertEquals("refs/heads/master", git2.getRepository().getFullBranch());
458 		assertEquals("refs/heads/master", allRefNames(git2.branchList()
459 				.setListMode(ListMode.ALL).call()));
460 		RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
461 				Constants.DEFAULT_REMOTE_NAME);
462 		List<RefSpec> specs = cfg.getFetchRefSpecs();
463 		assertEquals(1, specs.size());
464 		assertEquals(
465 				new RefSpec("+refs/heads/master:refs/heads/master"),
466 				specs.get(0));
467 	}
468 
469 	@Test
470 	public void testBareCloneRepositoryMirror() throws Exception {
471 		File directory = createTempDirectory(
472 				"testCloneRepositoryWithBranch_mirror");
473 		CloneCommand command = Git.cloneRepository();
474 		command.setBranch("refs/heads/master");
475 		command.setMirror(true); // implies bare repository
476 		command.setDirectory(directory);
477 		command.setURI(fileUri());
478 		Git git2 = command.call();
479 		addRepoToClose(git2.getRepository());
480 		assertTrue(git2.getRepository().isBare());
481 		assertNotNull(git2.getRepository().resolve("tag-for-blob"));
482 		assertNotNull(git2.getRepository().resolve("tag-initial"));
483 		assertEquals("refs/heads/master", git2.getRepository().getFullBranch());
484 		assertEquals("refs/heads/master, refs/heads/test", allRefNames(
485 				git2.branchList().setListMode(ListMode.ALL).call()));
486 		assertNotNull(git2.getRepository().exactRef("refs/meta/foo/bar"));
487 		RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
488 				Constants.DEFAULT_REMOTE_NAME);
489 		List<RefSpec> specs = cfg.getFetchRefSpecs();
490 		assertEquals(1, specs.size());
491 		assertEquals(new RefSpec("+refs/*:refs/*"),
492 				specs.get(0));
493 	}
494 
495 	@Test
496 	public void testCloneRepositoryOnlyOneTag() throws Exception {
497 		File directory = createTempDirectory("testCloneRepositoryWithBranch");
498 		CloneCommand command = Git.cloneRepository();
499 		command.setBranch("tag-initial");
500 		command.setBranchesToClone(
501 				Collections.singletonList("refs/tags/tag-initial"));
502 		command.setDirectory(directory);
503 		command.setURI(fileUri());
504 		Git git2 = command.call();
505 		addRepoToClose(git2.getRepository());
506 		assertNull(git2.getRepository().resolve("tag-for-blob"));
507 		assertNull(git2.getRepository().resolve("refs/heads/master"));
508 		assertNotNull(git2.getRepository().resolve("tag-initial"));
509 		ObjectId taggedCommit = db.resolve("tag-initial^{commit}");
510 		assertEquals(taggedCommit.name(), git2.getRepository().getFullBranch());
511 		RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
512 				Constants.DEFAULT_REMOTE_NAME);
513 		List<RefSpec> specs = cfg.getFetchRefSpecs();
514 		assertEquals(1, specs.size());
515 		assertEquals(
516 				new RefSpec("+refs/tags/tag-initial:refs/tags/tag-initial"),
517 				specs.get(0));
518 	}
519 
520 	@Test
521 	public void testCloneRepositoryAllBranchesTakesPreference()
522 			throws Exception {
523 		File directory = createTempDirectory(
524 				"testCloneRepositoryAllBranchesTakesPreference");
525 		CloneCommand command = Git.cloneRepository();
526 		command.setCloneAllBranches(true);
527 		command.setBranchesToClone(
528 				Collections.singletonList("refs/heads/test"));
529 		command.setDirectory(directory);
530 		command.setURI(fileUri());
531 		Git git2 = command.call();
532 		addRepoToClose(git2.getRepository());
533 		assertEquals("refs/heads/test", git2.getRepository().getFullBranch());
534 		// Expect both remote branches to exist; setCloneAllBranches(true)
535 		// should override any setBranchesToClone().
536 		assertNotNull(
537 				git2.getRepository().resolve("refs/remotes/origin/master"));
538 		assertNotNull(git2.getRepository().resolve("refs/remotes/origin/test"));
539 		RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
540 				Constants.DEFAULT_REMOTE_NAME);
541 		List<RefSpec> specs = cfg.getFetchRefSpecs();
542 		assertEquals(1, specs.size());
543 		assertEquals(new RefSpec("+refs/heads/*:refs/remotes/origin/*"),
544 				specs.get(0));
545 	}
546 
547 	@Test
548 	public void testCloneRepositoryAllBranchesIndependent() throws Exception {
549 		File directory = createTempDirectory(
550 				"testCloneRepositoryAllBranchesIndependent");
551 		CloneCommand command = Git.cloneRepository();
552 		command.setCloneAllBranches(true);
553 		command.setBranchesToClone(
554 				Collections.singletonList("refs/heads/test"));
555 		command.setCloneAllBranches(false);
556 		command.setDirectory(directory);
557 		command.setURI(fileUri());
558 		Git git2 = command.call();
559 		addRepoToClose(git2.getRepository());
560 		assertEquals("refs/heads/test", git2.getRepository().getFullBranch());
561 		// Expect only the test branch; allBranches was re-set to false
562 		assertNull(git2.getRepository().resolve("refs/remotes/origin/master"));
563 		assertNotNull(git2.getRepository().resolve("refs/remotes/origin/test"));
564 		RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
565 				Constants.DEFAULT_REMOTE_NAME);
566 		List<RefSpec> specs = cfg.getFetchRefSpecs();
567 		assertEquals(1, specs.size());
568 		assertEquals(new RefSpec("+refs/heads/test:refs/remotes/origin/test"),
569 				specs.get(0));
570 	}
571 
572 	public static String allRefNames(List<Ref> refs) {
573 		StringBuilder sb = new StringBuilder();
574 		for (Ref f : refs) {
575 			if (sb.length() > 0)
576 				sb.append(", ");
577 			sb.append(f.getName());
578 		}
579 		return sb.toString();
580 	}
581 
582 	@Test
583 	public void testCloneRepositoryWhenDestinationDirectoryExistsAndIsNotEmpty()
584 			throws IOException, JGitInternalException, GitAPIException {
585 		String dirName = "testCloneTargetDirectoryNotEmpty";
586 		File directory = createTempDirectory(dirName);
587 		CloneCommand command = Git.cloneRepository();
588 		command.setDirectory(directory);
589 		command.setURI(fileUri());
590 		Git git2 = command.call();
591 		addRepoToClose(git2.getRepository());
592 		// clone again
593 		command = Git.cloneRepository();
594 		command.setDirectory(directory);
595 		command.setURI(fileUri());
596 		try {
597 			git2 = command.call();
598 			// we shouldn't get here
599 			fail("destination directory already exists and is not an empty folder, cloning should fail");
600 		} catch (JGitInternalException e) {
601 			assertTrue(e.getMessage().contains("not an empty directory"));
602 			assertTrue(e.getMessage().contains(dirName));
603 		}
604 	}
605 
606 	@Test
607 	public void testCloneRepositoryWithMultipleHeadBranches() throws Exception {
608 		git.checkout().setName(Constants.MASTER).call();
609 		git.branchCreate().setName("a").call();
610 
611 		File directory = createTempDirectory("testCloneRepositoryWithMultipleHeadBranches");
612 		CloneCommand clone = Git.cloneRepository();
613 		clone.setDirectory(directory);
614 		clone.setURI(fileUri());
615 		Git git2 = clone.call();
616 		addRepoToClose(git2.getRepository());
617 
618 		assertEquals(Constants.MASTER, git2.getRepository().getBranch());
619 	}
620 
621 	@Test
622 	public void testCloneRepositoryWithSubmodules() throws Exception {
623 		git.checkout().setName(Constants.MASTER).call();
624 
625 		String file = "file.txt";
626 		writeTrashFile(file, "content");
627 		git.add().addFilepattern(file).call();
628 		RevCommit commit = git.commit().setMessage("create file").call();
629 
630 		SubmoduleAddCommand command = new SubmoduleAddCommand(db);
631 		String path = "sub";
632 		command.setPath(path);
633 		String uri = db.getDirectory().toURI().toString();
634 		command.setURI(uri);
635 		Repository repo = command.call();
636 		assertNotNull(repo);
637 		addRepoToClose(repo);
638 		git.add().addFilepattern(path)
639 				.addFilepattern(Constants.DOT_GIT_MODULES).call();
640 		git.commit().setMessage("adding submodule").call();
641 		try (SubmoduleWalk walk = SubmoduleWalk.forIndex(git.getRepository())) {
642 			assertTrue(walk.next());
643 			Repository subRepo = walk.getRepository();
644 			addRepoToClose(subRepo);
645 			assertNotNull(subRepo);
646 			assertEquals(
647 					new File(git.getRepository().getWorkTree(), walk.getPath()),
648 					subRepo.getWorkTree());
649 			assertEquals(new File(new File(git.getRepository().getDirectory(),
650 					"modules"), walk.getPath()), subRepo.getDirectory());
651 		}
652 
653 		File directory = createTempDirectory("testCloneRepositoryWithSubmodules");
654 		CloneCommand clone = Git.cloneRepository();
655 		clone.setDirectory(directory);
656 		clone.setCloneSubmodules(true);
657 		clone.setURI(fileUri());
658 		Git git2 = clone.call();
659 		addRepoToClose(git2.getRepository());
660 
661 		assertEquals(Constants.MASTER, git2.getRepository().getBranch());
662 		assertTrue(new File(git2.getRepository().getWorkTree(), path
663 				+ File.separatorChar + file).exists());
664 
665 		SubmoduleStatusCommand status = new SubmoduleStatusCommand(
666 				git2.getRepository());
667 		Map<String, SubmoduleStatus> statuses = status.call();
668 		SubmoduleStatus pathStatus = statuses.get(path);
669 		assertNotNull(pathStatus);
670 		assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType());
671 		assertEquals(commit, pathStatus.getHeadId());
672 		assertEquals(commit, pathStatus.getIndexId());
673 
674 		try (SubmoduleWalk walk = SubmoduleWalk
675 				.forIndex(git2.getRepository())) {
676 			assertTrue(walk.next());
677 			Repository clonedSub1 = walk.getRepository();
678 			addRepoToClose(clonedSub1);
679 			assertNotNull(clonedSub1);
680 			assertEquals(new File(git2.getRepository().getWorkTree(),
681 					walk.getPath()), clonedSub1.getWorkTree());
682 			assertEquals(
683 					new File(new File(git2.getRepository().getDirectory(),
684 							"modules"), walk.getPath()),
685 					clonedSub1.getDirectory());
686 		}
687 	}
688 
689 	@Test
690 	public void testCloneRepositoryWithNestedSubmodules() throws Exception {
691 		git.checkout().setName(Constants.MASTER).call();
692 
693 		// Create submodule 1
694 		File submodule1 = createTempDirectory("testCloneRepositoryWithNestedSubmodules1");
695 		Git sub1Git = Git.init().setDirectory(submodule1).call();
696 		assertNotNull(sub1Git);
697 		Repository sub1 = sub1Git.getRepository();
698 		assertNotNull(sub1);
699 		addRepoToClose(sub1);
700 
701 		String file = "file.txt";
702 		String path = "sub";
703 
704 		write(new File(sub1.getWorkTree(), file), "content");
705 		sub1Git.add().addFilepattern(file).call();
706 		RevCommit commit = sub1Git.commit().setMessage("create file").call();
707 		assertNotNull(commit);
708 
709 		// Create submodule 2
710 		File submodule2 = createTempDirectory("testCloneRepositoryWithNestedSubmodules2");
711 		Git sub2Git = Git.init().setDirectory(submodule2).call();
712 		assertNotNull(sub2Git);
713 		Repository sub2 = sub2Git.getRepository();
714 		assertNotNull(sub2);
715 		addRepoToClose(sub2);
716 
717 		write(new File(sub2.getWorkTree(), file), "content");
718 		sub2Git.add().addFilepattern(file).call();
719 		RevCommit sub2Head = sub2Git.commit().setMessage("create file").call();
720 		assertNotNull(sub2Head);
721 
722 		// Add submodule 2 to submodule 1
723 		Repository r = sub1Git.submoduleAdd().setPath(path)
724 				.setURI(sub2.getDirectory().toURI().toString()).call();
725 		assertNotNull(r);
726 		addRepoToClose(r);
727 		RevCommit sub1Head = sub1Git.commit().setAll(true)
728 				.setMessage("Adding submodule").call();
729 		assertNotNull(sub1Head);
730 
731 		// Add submodule 1 to default repository
732 		r = git.submoduleAdd().setPath(path)
733 				.setURI(sub1.getDirectory().toURI().toString()).call();
734 		assertNotNull(r);
735 		addRepoToClose(r);
736 		assertNotNull(git.commit().setAll(true).setMessage("Adding submodule")
737 				.call());
738 
739 		// Clone default repository and include submodules
740 		File directory = createTempDirectory("testCloneRepositoryWithNestedSubmodules");
741 		CloneCommand clone = Git.cloneRepository();
742 		clone.setDirectory(directory);
743 		clone.setCloneSubmodules(true);
744 		clone.setURI(git.getRepository().getDirectory().toURI().toString());
745 		Git git2 = clone.call();
746 		addRepoToClose(git2.getRepository());
747 
748 		assertEquals(Constants.MASTER, git2.getRepository().getBranch());
749 		assertTrue(new File(git2.getRepository().getWorkTree(), path
750 				+ File.separatorChar + file).exists());
751 		assertTrue(new File(git2.getRepository().getWorkTree(), path
752 				+ File.separatorChar + path + File.separatorChar + file)
753 				.exists());
754 
755 		SubmoduleStatusCommand status = new SubmoduleStatusCommand(
756 				git2.getRepository());
757 		Map<String, SubmoduleStatus> statuses = status.call();
758 		SubmoduleStatus pathStatus = statuses.get(path);
759 		assertNotNull(pathStatus);
760 		assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType());
761 		assertEquals(sub1Head, pathStatus.getHeadId());
762 		assertEquals(sub1Head, pathStatus.getIndexId());
763 
764 		try (SubmoduleWalk walk = SubmoduleWalk
765 				.forIndex(git2.getRepository())) {
766 			assertTrue(walk.next());
767 			try (Repository clonedSub1 = walk.getRepository()) {
768 				assertNotNull(clonedSub1);
769 				assertEquals(new File(git2.getRepository().getWorkTree(),
770 						walk.getPath()), clonedSub1.getWorkTree());
771 				assertEquals(
772 						new File(new File(git2.getRepository().getDirectory(),
773 								"modules"), walk.getPath()),
774 						clonedSub1.getDirectory());
775 				status = new SubmoduleStatusCommand(clonedSub1);
776 				statuses = status.call();
777 			}
778 			assertFalse(walk.next());
779 		}
780 		pathStatus = statuses.get(path);
781 		assertNotNull(pathStatus);
782 		assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType());
783 		assertEquals(sub2Head, pathStatus.getHeadId());
784 		assertEquals(sub2Head, pathStatus.getIndexId());
785 	}
786 
787 	@Test
788 	public void testCloneWithAutoSetupRebase() throws Exception {
789 		File directory = createTempDirectory("testCloneRepository1");
790 		CloneCommand command = Git.cloneRepository();
791 		command.setDirectory(directory);
792 		command.setURI(fileUri());
793 		Git git2 = command.call();
794 		addRepoToClose(git2.getRepository());
795 		assertNull(git2.getRepository().getConfig().getEnum(
796 				BranchRebaseMode.values(),
797 				ConfigConstants.CONFIG_BRANCH_SECTION, "test",
798 				ConfigConstants.CONFIG_KEY_REBASE, null));
799 
800 		StoredConfig userConfig = SystemReader.getInstance()
801 				.getUserConfig();
802 		userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null,
803 				ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE,
804 				ConfigConstants.CONFIG_KEY_ALWAYS);
805 		userConfig.save();
806 		directory = createTempDirectory("testCloneRepository2");
807 		command = Git.cloneRepository();
808 		command.setDirectory(directory);
809 		command.setURI(fileUri());
810 		git2 = command.call();
811 		addRepoToClose(git2.getRepository());
812 		assertEquals(BranchRebaseMode.REBASE,
813 				git2.getRepository().getConfig().getEnum(
814 						BranchRebaseMode.values(),
815 						ConfigConstants.CONFIG_BRANCH_SECTION, "test",
816 						ConfigConstants.CONFIG_KEY_REBASE,
817 						BranchRebaseMode.NONE));
818 
819 		userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null,
820 				ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE,
821 				ConfigConstants.CONFIG_KEY_REMOTE);
822 		userConfig.save();
823 		directory = createTempDirectory("testCloneRepository2");
824 		command = Git.cloneRepository();
825 		command.setDirectory(directory);
826 		command.setURI(fileUri());
827 		git2 = command.call();
828 		addRepoToClose(git2.getRepository());
829 		assertEquals(BranchRebaseMode.REBASE,
830 				git2.getRepository().getConfig().getEnum(
831 						BranchRebaseMode.values(),
832 						ConfigConstants.CONFIG_BRANCH_SECTION, "test",
833 						ConfigConstants.CONFIG_KEY_REBASE,
834 						BranchRebaseMode.NONE));
835 
836 	}
837 
838 	@Test
839 	public void testCloneWithPullMerge() throws Exception {
840 		File directory = createTempDirectory("testCloneRepository1");
841 		try (Git g = Git.init().setDirectory(directory).setBare(false).call()) {
842 			g.remoteAdd().setName(Constants.DEFAULT_REMOTE_NAME)
843 					.setUri(new URIish(fileUri())).call();
844 			PullResult result = g.pull().setRebase(false).call();
845 			assertTrue(result.isSuccessful());
846 			assertEquals("refs/heads/master",
847 					g.getRepository().getFullBranch());
848 			checkFile(new File(directory, "Test.txt"), "Hello world");
849 		}
850 	}
851 
852 	@Test
853 	public void testCloneWithPullRebase() throws Exception {
854 		File directory = createTempDirectory("testCloneRepository1");
855 		try (Git g = Git.init().setDirectory(directory).setBare(false).call()) {
856 			g.remoteAdd().setName(Constants.DEFAULT_REMOTE_NAME)
857 					.setUri(new URIish(fileUri())).call();
858 			PullResult result = g.pull().setRebase(true).call();
859 			assertTrue(result.isSuccessful());
860 			assertEquals("refs/heads/master",
861 					g.getRepository().getFullBranch());
862 			checkFile(new File(directory, "Test.txt"), "Hello world");
863 		}
864 	}
865 
866 	@Test
867 	public void testCloneNoTags() throws IOException, JGitInternalException,
868 			GitAPIException, URISyntaxException {
869 		File directory = createTempDirectory("testCloneRepository");
870 		CloneCommand command = Git.cloneRepository();
871 		command.setDirectory(directory);
872 		command.setURI(fileUri());
873 		command.setNoTags();
874 		Git git2 = command.call();
875 		addRepoToClose(git2.getRepository());
876 		assertNotNull(git2.getRepository().resolve("refs/heads/test"));
877 		assertNull(git2.getRepository().resolve("tag-initial"));
878 		assertNull(git2.getRepository().resolve("tag-for-blob"));
879 		assertTagOption(git2.getRepository(), TagOpt.NO_TAGS);
880 	}
881 
882 	@Test
883 	public void testCloneFollowTags() throws IOException, JGitInternalException,
884 			GitAPIException, URISyntaxException {
885 		File directory = createTempDirectory("testCloneRepository");
886 		CloneCommand command = Git.cloneRepository();
887 		command.setDirectory(directory);
888 		command.setURI(fileUri());
889 		command.setBranch("refs/heads/master");
890 		command.setBranchesToClone(
891 				Collections.singletonList("refs/heads/master"));
892 		command.setTagOption(TagOpt.FETCH_TAGS);
893 		Git git2 = command.call();
894 		addRepoToClose(git2.getRepository());
895 		assertNull(git2.getRepository().resolve("refs/heads/test"));
896 		assertNotNull(git2.getRepository().resolve("tag-initial"));
897 		assertNotNull(git2.getRepository().resolve("tag-for-blob"));
898 		assertTagOption(git2.getRepository(), TagOpt.FETCH_TAGS);
899 	}
900 
901 	@Test
902 	public void testCloneWithHeadSymRefIsMasterCopy() throws IOException, GitAPIException {
903 		// create a branch with the same head as master and switch to it
904 		git.checkout().setStartPoint("master").setCreateBranch(true).setName("master-copy").call();
905 
906 		// when we clone the HEAD symref->master-copy means we start on master-copy and not master
907 		File directory = createTempDirectory("testCloneRepositorySymRef_master-copy");
908 		CloneCommand command = Git.cloneRepository();
909 		command.setDirectory(directory);
910 		command.setURI(fileUri());
911 		Git git2 = command.call();
912 		addRepoToClose(git2.getRepository());
913 		assertEquals("refs/heads/master-copy", git2.getRepository().getFullBranch());
914 	}
915 
916 	@Test
917 	public void testCloneWithHeadSymRefIsNonMasterCopy() throws IOException, GitAPIException {
918 		// create a branch with the same head as test and switch to it
919 		git.checkout().setStartPoint("test").setCreateBranch(true).setName("test-copy").call();
920 
921 		File directory = createTempDirectory("testCloneRepositorySymRef_test-copy");
922 		CloneCommand command = Git.cloneRepository();
923 		command.setDirectory(directory);
924 		command.setURI(fileUri());
925 		Git git2 = command.call();
926 		addRepoToClose(git2.getRepository());
927 		assertEquals("refs/heads/test-copy", git2.getRepository().getFullBranch());
928 	}
929 
930     @Test
931     public void testCloneRepositoryWithDepth() throws IOException, JGitInternalException, GitAPIException {
932 		File directory = createTempDirectory("testCloneRepositoryWithDepth");
933 		CloneCommand command = Git.cloneRepository();
934 		command.setDirectory(directory);
935 		command.setURI(fileUri());
936         command.setDepth(1);
937 		command.setBranchesToClone(Set.of("refs/heads/test"));
938 		Git git2 = command.call();
939 		addRepoToClose(git2.getRepository());
940 
941 		List<RevCommit> log = StreamSupport.stream(git2.log().all().call().spliterator(), false)
942 				.collect(Collectors.toList());
943 		assertEquals(1, log.size());
944 		RevCommit commit = log.get(0);
945 		assertEquals(Set.of(commit.getId()),
946 				git2.getRepository().getObjectDatabase().getShallowCommits());
947 		assertEquals("Second commit", commit.getFullMessage());
948 		assertEquals(0, commit.getParentCount());
949 	}
950 
951 	@Test
952 	public void testCloneRepositoryWithDepthAndAllBranches() throws IOException, JGitInternalException, GitAPIException {
953 		File directory = createTempDirectory("testCloneRepositoryWithDepthAndAllBranches");
954 		CloneCommand command = Git.cloneRepository();
955 		command.setDirectory(directory);
956 		command.setURI(fileUri());
957 		command.setDepth(1);
958 		command.setCloneAllBranches(true);
959 		Git git2 = command.call();
960 		addRepoToClose(git2.getRepository());
961 
962 		List<RevCommit> log = StreamSupport.stream(git2.log().all().call().spliterator(), false)
963 				.collect(Collectors.toList());
964 		assertEquals(2, log.size());
965 		assertEquals(log.stream().map(RevCommit::getId).collect(Collectors.toSet()),
966 				git2.getRepository().getObjectDatabase().getShallowCommits());
967 		assertEquals(List.of("Second commit", "Initial commit"),
968 				log.stream().map(RevCommit::getFullMessage).collect(Collectors.toList()));
969 		for (RevCommit commit : log) {
970 			assertEquals(0, commit.getParentCount());
971 		}
972 	}
973 
974 	@Test
975 	public void testCloneRepositoryWithDepth2() throws Exception {
976 		RevCommit parent = tr.git().log().call().iterator().next();
977 		RevCommit commit = tr.commit()
978 				.parent(parent)
979 				.message("Third commit")
980 				.add("test.txt", "Hello world")
981 				.create();
982 		tr.update("refs/heads/test", commit);
983 
984 		File directory = createTempDirectory("testCloneRepositoryWithDepth2");
985 		CloneCommand command = Git.cloneRepository();
986 		command.setDirectory(directory);
987 		command.setURI(fileUri());
988 		command.setDepth(2);
989 		command.setBranchesToClone(Set.of("refs/heads/test"));
990 		Git git2 = command.call();
991 		addRepoToClose(git2.getRepository());
992 
993 		List<RevCommit> log = StreamSupport
994 				.stream(git2.log().all().call().spliterator(), false)
995 				.collect(Collectors.toList());
996 		assertEquals(2, log.size());
997 		assertEquals(Set.of(parent.getId()),
998 				git2.getRepository().getObjectDatabase().getShallowCommits());
999 		assertEquals(List.of("Third commit", "Second commit"), log.stream()
1000 				.map(RevCommit::getFullMessage).collect(Collectors.toList()));
1001 		assertEquals(List.of(Integer.valueOf(1), Integer.valueOf(0)),
1002 				log.stream().map(RevCommit::getParentCount)
1003 						.collect(Collectors.toList()));
1004 	}
1005 
1006 	@Test
1007 	public void testCloneRepositoryWithDepthAndFetch() throws Exception {
1008 		File directory = createTempDirectory("testCloneRepositoryWithDepthAndFetch");
1009 		CloneCommand command = Git.cloneRepository();
1010 		command.setDirectory(directory);
1011 		command.setURI(fileUri());
1012 		command.setDepth(1);
1013 		command.setBranchesToClone(Set.of("refs/heads/test"));
1014 		Git git2 = command.call();
1015 		addRepoToClose(git2.getRepository());
1016 
1017 		RevCommit parent = tr.git().log().call().iterator().next();
1018 		RevCommit commit = tr.commit()
1019 				.parent(parent)
1020 				.message("Third commit")
1021 				.add("test.txt", "Hello world")
1022 				.create();
1023 		tr.update("refs/heads/test", commit);
1024 
1025 		git2.fetch().call();
1026 
1027 		List<RevCommit> log = StreamSupport
1028 				.stream(git2.log().all().call().spliterator(), false)
1029 				.collect(Collectors.toList());
1030 		assertEquals(2, log.size());
1031 		assertEquals(Set.of(parent.getId()),
1032 				git2.getRepository().getObjectDatabase().getShallowCommits());
1033 		assertEquals(List.of("Third commit", "Second commit"), log.stream()
1034 				.map(RevCommit::getFullMessage).collect(Collectors.toList()));
1035 		assertEquals(List.of(Integer.valueOf(1), Integer.valueOf(0)),
1036 				log.stream().map(RevCommit::getParentCount)
1037 						.collect(Collectors.toList()));
1038 	}
1039 
1040 	@Test
1041 	public void testCloneRepositoryWithDepthAndFetchWithDepth() throws Exception {
1042 		File directory = createTempDirectory("testCloneRepositoryWithDepthAndFetchWithDepth");
1043 		CloneCommand command = Git.cloneRepository();
1044 		command.setDirectory(directory);
1045 		command.setURI(fileUri());
1046 		command.setDepth(1);
1047 		command.setBranchesToClone(Set.of("refs/heads/test"));
1048 		Git git2 = command.call();
1049 		addRepoToClose(git2.getRepository());
1050 
1051 		RevCommit parent = tr.git().log().call().iterator().next();
1052 		RevCommit commit = tr.commit()
1053 				.parent(parent)
1054 				.message("Third commit")
1055 				.add("test.txt", "Hello world")
1056 				.create();
1057 		tr.update("refs/heads/test", commit);
1058 
1059 		git2.fetch().setDepth(1).call();
1060 
1061 		List<RevCommit> log = StreamSupport
1062 				.stream(git2.log().all().call().spliterator(), false)
1063 				.collect(Collectors.toList());
1064 		assertEquals(2, log.size());
1065 		assertEquals(
1066 				log.stream().map(RevObject::getId).collect(Collectors.toSet()),
1067 				git2.getRepository().getObjectDatabase().getShallowCommits());
1068 		assertEquals(List.of("Third commit", "Second commit"), log.stream()
1069 				.map(RevCommit::getFullMessage).collect(Collectors.toList()));
1070 		assertEquals(List.of(Integer.valueOf(0), Integer.valueOf(0)),
1071 				log.stream().map(RevCommit::getParentCount)
1072 						.collect(Collectors.toList()));
1073 	}
1074 
1075 	@Test
1076 	public void testCloneRepositoryWithDepthAndFetchUnshallow() throws Exception {
1077 		File directory = createTempDirectory("testCloneRepositoryWithDepthAndFetchUnshallow");
1078 		CloneCommand command = Git.cloneRepository();
1079 		command.setDirectory(directory);
1080 		command.setURI(fileUri());
1081 		command.setDepth(1);
1082 		command.setBranchesToClone(Set.of("refs/heads/test"));
1083 		Git git2 = command.call();
1084 		addRepoToClose(git2.getRepository());
1085 
1086 		git2.fetch().setUnshallow(true).call();
1087 
1088 		List<RevCommit> log = StreamSupport
1089 				.stream(git2.log().all().call().spliterator(), false)
1090 				.collect(Collectors.toList());
1091 		assertEquals(2, log.size());
1092 		assertEquals(Set.of(),
1093 				git2.getRepository().getObjectDatabase().getShallowCommits());
1094 		assertEquals(List.of("Second commit", "Initial commit"), log.stream()
1095 				.map(RevCommit::getFullMessage).collect(Collectors.toList()));
1096 		assertEquals(List.of(Integer.valueOf(1), Integer.valueOf(0)),
1097 				log.stream().map(RevCommit::getParentCount)
1098 						.collect(Collectors.toList()));
1099 	}
1100 
1101     @Test
1102 	public void testCloneRepositoryWithShallowSince() throws Exception {
1103 		RevCommit commit = tr.commit()
1104 				.parent(tr.git().log().call().iterator().next())
1105 				.message("Third commit").add("test.txt", "Hello world")
1106 				.create();
1107 		tr.update("refs/heads/test", commit);
1108 
1109         File directory = createTempDirectory("testCloneRepositoryWithShallowSince");
1110         CloneCommand command = Git.cloneRepository();
1111         command.setDirectory(directory);
1112         command.setURI(fileUri());
1113         command.setShallowSince(Instant.ofEpochSecond(commit.getCommitTime()));
1114         command.setBranchesToClone(Set.of("refs/heads/test"));
1115         Git git2 = command.call();
1116         addRepoToClose(git2.getRepository());
1117 
1118 		List<RevCommit> log = StreamSupport
1119 				.stream(git2.log().all().call().spliterator(), false)
1120 				.collect(Collectors.toList());
1121 		assertEquals(1, log.size());
1122 		assertEquals(Set.of(commit.getId()),
1123 				git2.getRepository().getObjectDatabase().getShallowCommits());
1124 		assertEquals("Third commit", log.get(0).getFullMessage());
1125 		assertEquals(0, log.get(0).getParentCount());
1126     }
1127 
1128 	@Test
1129 	public void testCloneRepositoryWithShallowExclude() throws Exception {
1130 		RevCommit parent = tr.git().log().call().iterator().next();
1131 		tr.update("refs/heads/test",
1132 				tr.commit()
1133 					.parent(parent)
1134 					.message("Third commit")
1135 					.add("test.txt", "Hello world")
1136 					.create());
1137 
1138 		File directory = createTempDirectory("testCloneRepositoryWithShallowExclude");
1139 		CloneCommand command = Git.cloneRepository();
1140 		command.setDirectory(directory);
1141 		command.setURI(fileUri());
1142 		command.addShallowExclude(parent.getId());
1143 		command.setBranchesToClone(Set.of("refs/heads/test"));
1144 		Git git2 = command.call();
1145 		addRepoToClose(git2.getRepository());
1146 
1147 		List<RevCommit> log = StreamSupport
1148 				.stream(git2.log().all().call().spliterator(), false)
1149 				.collect(Collectors.toList());
1150 		assertEquals(1, log.size());
1151 		RevCommit commit = log.get(0);
1152 		assertEquals(Set.of(commit.getId()),
1153 				git2.getRepository().getObjectDatabase().getShallowCommits());
1154 		assertEquals("Third commit", commit.getFullMessage());
1155 		assertEquals(0, commit.getParentCount());
1156 	}
1157 
1158 	private void assertTagOption(Repository repo, TagOpt expectedTagOption)
1159 			throws URISyntaxException {
1160 		RemoteConfig remoteConfig = new RemoteConfig(
1161 				repo.getConfig(), "origin");
1162 		assertEquals(expectedTagOption, remoteConfig.getTagOpt());
1163 	}
1164 
1165 	private String fileUri() {
1166 		return "file://" + git.getRepository().getWorkTree().getAbsolutePath();
1167 	}
1168 }