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