You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CloneCommandTest.java 19KB

Fix corrupted CloneCommand bare-repo fetch-refspec (#402031) CloneCommand has been creating fetch refspecs like this on bare clones: [remote "origin"] url = ssh://example.com/my-repo.git fetch = +refs/heads/*:refs/heads//* As you can see, the destination ref pattern has a superfluous slash. It looks like this behaviour has always been the case for CloneCommand, at least since cc2197ed when code catering to bare-clone fetch refspecs was added. That was released with JGit v1.0 almost 2 years ago, so there will probably be some bare repos in the wild which will have been cloned with JGit and have these corrupted refspecs. The effect of the corrupted fetch refspec is quite interesting. Up to and including JGit 2.0, the corrupt refspec was tolerated and fetches would work as intended with no indication to the user that anything was amiss. With JGit 2.1, a change was introduced which made JGit less tolerant, and fetches now attempt to update the non-existing ref "refs/heads//master". No exception is raised, but the real ref - "refs/heads/master" - is not updated. This behaviour was noticed by a user of Agit (which does bare clones by default and recently updated from JGit v2.0 to v2.2), reported here: https://github.com/rtyley/agit/issues/92 If you run C-Git fetch on a bare-repo cloned by JGit, it flat-out rejects the refspec (checked against v1.7.10.4): fatal: Invalid refspec '+refs/heads/*:refs/heads//*' Incidentally, C-Git does not create an explicit fetch refspec at all when performing a bare clone - the full remote config generated by C-Git looks like this: [remote "origin"] url = ssh://example.com/my-repo.git Using JGit on such a repository works fine, so omitting the fetch refspec entirely is also an option. Change-Id: I14b0d359dc69b8908f68e02cea7a756ac34bf881
11 years ago
Fix corrupted CloneCommand bare-repo fetch-refspec (#402031) CloneCommand has been creating fetch refspecs like this on bare clones: [remote "origin"] url = ssh://example.com/my-repo.git fetch = +refs/heads/*:refs/heads//* As you can see, the destination ref pattern has a superfluous slash. It looks like this behaviour has always been the case for CloneCommand, at least since cc2197ed when code catering to bare-clone fetch refspecs was added. That was released with JGit v1.0 almost 2 years ago, so there will probably be some bare repos in the wild which will have been cloned with JGit and have these corrupted refspecs. The effect of the corrupted fetch refspec is quite interesting. Up to and including JGit 2.0, the corrupt refspec was tolerated and fetches would work as intended with no indication to the user that anything was amiss. With JGit 2.1, a change was introduced which made JGit less tolerant, and fetches now attempt to update the non-existing ref "refs/heads//master". No exception is raised, but the real ref - "refs/heads/master" - is not updated. This behaviour was noticed by a user of Agit (which does bare clones by default and recently updated from JGit v2.0 to v2.2), reported here: https://github.com/rtyley/agit/issues/92 If you run C-Git fetch on a bare-repo cloned by JGit, it flat-out rejects the refspec (checked against v1.7.10.4): fatal: Invalid refspec '+refs/heads/*:refs/heads//*' Incidentally, C-Git does not create an explicit fetch refspec at all when performing a bare clone - the full remote config generated by C-Git looks like this: [remote "origin"] url = ssh://example.com/my-repo.git Using JGit on such a repository works fine, so omitting the fetch refspec entirely is also an option. Change-Id: I14b0d359dc69b8908f68e02cea7a756ac34bf881
11 years ago
Fix corrupted CloneCommand bare-repo fetch-refspec (#402031) CloneCommand has been creating fetch refspecs like this on bare clones: [remote "origin"] url = ssh://example.com/my-repo.git fetch = +refs/heads/*:refs/heads//* As you can see, the destination ref pattern has a superfluous slash. It looks like this behaviour has always been the case for CloneCommand, at least since cc2197ed when code catering to bare-clone fetch refspecs was added. That was released with JGit v1.0 almost 2 years ago, so there will probably be some bare repos in the wild which will have been cloned with JGit and have these corrupted refspecs. The effect of the corrupted fetch refspec is quite interesting. Up to and including JGit 2.0, the corrupt refspec was tolerated and fetches would work as intended with no indication to the user that anything was amiss. With JGit 2.1, a change was introduced which made JGit less tolerant, and fetches now attempt to update the non-existing ref "refs/heads//master". No exception is raised, but the real ref - "refs/heads/master" - is not updated. This behaviour was noticed by a user of Agit (which does bare clones by default and recently updated from JGit v2.0 to v2.2), reported here: https://github.com/rtyley/agit/issues/92 If you run C-Git fetch on a bare-repo cloned by JGit, it flat-out rejects the refspec (checked against v1.7.10.4): fatal: Invalid refspec '+refs/heads/*:refs/heads//*' Incidentally, C-Git does not create an explicit fetch refspec at all when performing a bare clone - the full remote config generated by C-Git looks like this: [remote "origin"] url = ssh://example.com/my-repo.git Using JGit on such a repository works fine, so omitting the fetch refspec entirely is also an option. Change-Id: I14b0d359dc69b8908f68e02cea7a756ac34bf881
11 years ago
Fix corrupted CloneCommand bare-repo fetch-refspec (#402031) CloneCommand has been creating fetch refspecs like this on bare clones: [remote "origin"] url = ssh://example.com/my-repo.git fetch = +refs/heads/*:refs/heads//* As you can see, the destination ref pattern has a superfluous slash. It looks like this behaviour has always been the case for CloneCommand, at least since cc2197ed when code catering to bare-clone fetch refspecs was added. That was released with JGit v1.0 almost 2 years ago, so there will probably be some bare repos in the wild which will have been cloned with JGit and have these corrupted refspecs. The effect of the corrupted fetch refspec is quite interesting. Up to and including JGit 2.0, the corrupt refspec was tolerated and fetches would work as intended with no indication to the user that anything was amiss. With JGit 2.1, a change was introduced which made JGit less tolerant, and fetches now attempt to update the non-existing ref "refs/heads//master". No exception is raised, but the real ref - "refs/heads/master" - is not updated. This behaviour was noticed by a user of Agit (which does bare clones by default and recently updated from JGit v2.0 to v2.2), reported here: https://github.com/rtyley/agit/issues/92 If you run C-Git fetch on a bare-repo cloned by JGit, it flat-out rejects the refspec (checked against v1.7.10.4): fatal: Invalid refspec '+refs/heads/*:refs/heads//*' Incidentally, C-Git does not create an explicit fetch refspec at all when performing a bare clone - the full remote config generated by C-Git looks like this: [remote "origin"] url = ssh://example.com/my-repo.git Using JGit on such a repository works fine, so omitting the fetch refspec entirely is also an option. Change-Id: I14b0d359dc69b8908f68e02cea7a756ac34bf881
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /*
  2. * Copyright (C) 2011, 2013 Chris Aniszczyk <caniszczyk@gmail.com>
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.api;
  44. import static org.junit.Assert.assertEquals;
  45. import static org.junit.Assert.assertFalse;
  46. import static org.junit.Assert.assertNotNull;
  47. import static org.junit.Assert.assertTrue;
  48. import static org.junit.Assert.fail;
  49. import java.io.File;
  50. import java.io.IOException;
  51. import java.net.URISyntaxException;
  52. import java.util.Collections;
  53. import java.util.List;
  54. import java.util.Map;
  55. import org.eclipse.jgit.api.ListBranchCommand.ListMode;
  56. import org.eclipse.jgit.api.errors.GitAPIException;
  57. import org.eclipse.jgit.api.errors.JGitInternalException;
  58. import org.eclipse.jgit.junit.RepositoryTestCase;
  59. import org.eclipse.jgit.junit.TestRepository;
  60. import org.eclipse.jgit.lib.ConfigConstants;
  61. import org.eclipse.jgit.lib.Constants;
  62. import org.eclipse.jgit.lib.ObjectId;
  63. import org.eclipse.jgit.lib.Ref;
  64. import org.eclipse.jgit.lib.Repository;
  65. import org.eclipse.jgit.revwalk.RevBlob;
  66. import org.eclipse.jgit.revwalk.RevCommit;
  67. import org.eclipse.jgit.storage.file.FileBasedConfig;
  68. import org.eclipse.jgit.submodule.SubmoduleStatus;
  69. import org.eclipse.jgit.submodule.SubmoduleStatusType;
  70. import org.eclipse.jgit.submodule.SubmoduleWalk;
  71. import org.eclipse.jgit.transport.RefSpec;
  72. import org.eclipse.jgit.transport.RemoteConfig;
  73. import org.eclipse.jgit.util.SystemReader;
  74. import org.junit.Test;
  75. public class CloneCommandTest extends RepositoryTestCase {
  76. private Git git;
  77. private TestRepository<Repository> tr;
  78. public void setUp() throws Exception {
  79. super.setUp();
  80. tr = new TestRepository<Repository>(db);
  81. git = new Git(db);
  82. // commit something
  83. writeTrashFile("Test.txt", "Hello world");
  84. git.add().addFilepattern("Test.txt").call();
  85. git.commit().setMessage("Initial commit").call();
  86. git.tag().setName("tag-initial").setMessage("Tag initial").call();
  87. // create a test branch and switch to it
  88. git.checkout().setCreateBranch(true).setName("test").call();
  89. // commit something on the test branch
  90. writeTrashFile("Test.txt", "Some change");
  91. git.add().addFilepattern("Test.txt").call();
  92. git.commit().setMessage("Second commit").call();
  93. RevBlob blob = tr.blob("blob-not-in-master-branch");
  94. git.tag().setName("tag-for-blob").setObjectId(blob).call();
  95. }
  96. @Test
  97. public void testCloneRepository() throws IOException,
  98. JGitInternalException, GitAPIException, URISyntaxException {
  99. File directory = createTempDirectory("testCloneRepository");
  100. CloneCommand command = Git.cloneRepository();
  101. command.setDirectory(directory);
  102. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  103. Git git2 = command.call();
  104. addRepoToClose(git2.getRepository());
  105. assertNotNull(git2);
  106. ObjectId id = git2.getRepository().resolve("tag-for-blob");
  107. assertNotNull(id);
  108. assertEquals(git2.getRepository().getFullBranch(), "refs/heads/test");
  109. assertEquals(
  110. "origin",
  111. git2.getRepository()
  112. .getConfig()
  113. .getString(ConfigConstants.CONFIG_BRANCH_SECTION,
  114. "test", ConfigConstants.CONFIG_KEY_REMOTE));
  115. assertEquals(
  116. "refs/heads/test",
  117. git2.getRepository()
  118. .getConfig()
  119. .getString(ConfigConstants.CONFIG_BRANCH_SECTION,
  120. "test", ConfigConstants.CONFIG_KEY_MERGE));
  121. assertEquals(2, git2.branchList().setListMode(ListMode.REMOTE).call()
  122. .size());
  123. assertEquals(new RefSpec("+refs/heads/*:refs/remotes/origin/*"),
  124. fetchRefSpec(git2.getRepository()));
  125. }
  126. @Test
  127. public void testBareCloneRepository() throws IOException,
  128. JGitInternalException, GitAPIException, URISyntaxException {
  129. File directory = createTempDirectory("testCloneRepository_bare");
  130. CloneCommand command = Git.cloneRepository();
  131. command.setBare(true);
  132. command.setDirectory(directory);
  133. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  134. Git git2 = command.call();
  135. addRepoToClose(git2.getRepository());
  136. assertEquals(new RefSpec("+refs/heads/*:refs/heads/*"),
  137. fetchRefSpec(git2.getRepository()));
  138. }
  139. public static RefSpec fetchRefSpec(Repository r) throws URISyntaxException {
  140. RemoteConfig remoteConfig =
  141. new RemoteConfig(r.getConfig(), Constants.DEFAULT_REMOTE_NAME);
  142. return remoteConfig.getFetchRefSpecs().get(0);
  143. }
  144. @Test
  145. public void testCloneRepositoryWithBranch() throws IOException,
  146. JGitInternalException, GitAPIException {
  147. File directory = createTempDirectory("testCloneRepositoryWithBranch");
  148. CloneCommand command = Git.cloneRepository();
  149. command.setBranch("refs/heads/master");
  150. command.setDirectory(directory);
  151. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  152. Git git2 = command.call();
  153. addRepoToClose(git2.getRepository());
  154. assertNotNull(git2);
  155. assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
  156. assertEquals(
  157. "refs/heads/master, refs/remotes/origin/master, refs/remotes/origin/test",
  158. allRefNames(git2.branchList().setListMode(ListMode.ALL).call()));
  159. // Same thing, but now without checkout
  160. directory = createTempDirectory("testCloneRepositoryWithBranch_bare");
  161. command = Git.cloneRepository();
  162. command.setBranch("refs/heads/master");
  163. command.setDirectory(directory);
  164. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  165. command.setNoCheckout(true);
  166. git2 = command.call();
  167. addRepoToClose(git2.getRepository());
  168. assertNotNull(git2);
  169. assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
  170. assertEquals("refs/remotes/origin/master, refs/remotes/origin/test",
  171. allRefNames(git2.branchList().setListMode(ListMode.ALL).call()));
  172. // Same thing, but now test with bare repo
  173. directory = createTempDirectory("testCloneRepositoryWithBranch_bare");
  174. command = Git.cloneRepository();
  175. command.setBranch("refs/heads/master");
  176. command.setDirectory(directory);
  177. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  178. command.setBare(true);
  179. git2 = command.call();
  180. addRepoToClose(git2.getRepository());
  181. assertNotNull(git2);
  182. assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
  183. assertEquals("refs/heads/master, refs/heads/test", allRefNames(git2
  184. .branchList().setListMode(ListMode.ALL).call()));
  185. }
  186. @Test
  187. public void testCloneRepositoryWithBranchShortName() throws Exception {
  188. File directory = createTempDirectory("testCloneRepositoryWithBranch");
  189. CloneCommand command = Git.cloneRepository();
  190. command.setBranch("test");
  191. command.setDirectory(directory);
  192. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  193. Git git2 = command.call();
  194. addRepoToClose(git2.getRepository());
  195. assertNotNull(git2);
  196. assertEquals("refs/heads/test", git2.getRepository().getFullBranch());
  197. }
  198. @Test
  199. public void testCloneRepositoryWithTagName() throws Exception {
  200. File directory = createTempDirectory("testCloneRepositoryWithBranch");
  201. CloneCommand command = Git.cloneRepository();
  202. command.setBranch("tag-initial");
  203. command.setDirectory(directory);
  204. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  205. Git git2 = command.call();
  206. addRepoToClose(git2.getRepository());
  207. assertNotNull(git2);
  208. ObjectId taggedCommit = db.resolve("tag-initial^{commit}");
  209. assertEquals(taggedCommit.name(), git2
  210. .getRepository().getFullBranch());
  211. }
  212. @Test
  213. public void testCloneRepositoryOnlyOneBranch() throws IOException,
  214. JGitInternalException, GitAPIException {
  215. File directory = createTempDirectory("testCloneRepositoryWithBranch");
  216. CloneCommand command = Git.cloneRepository();
  217. command.setBranch("refs/heads/master");
  218. command.setBranchesToClone(Collections
  219. .singletonList("refs/heads/master"));
  220. command.setDirectory(directory);
  221. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  222. Git git2 = command.call();
  223. addRepoToClose(git2.getRepository());
  224. assertNotNull(git2);
  225. assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
  226. assertEquals("refs/remotes/origin/master", allRefNames(git2
  227. .branchList().setListMode(ListMode.REMOTE).call()));
  228. // Same thing, but now test with bare repo
  229. directory = createTempDirectory("testCloneRepositoryWithBranch_bare");
  230. command = Git.cloneRepository();
  231. command.setBranch("refs/heads/master");
  232. command.setBranchesToClone(Collections
  233. .singletonList("refs/heads/master"));
  234. command.setDirectory(directory);
  235. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  236. command.setBare(true);
  237. git2 = command.call();
  238. addRepoToClose(git2.getRepository());
  239. assertNotNull(git2);
  240. assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
  241. assertEquals("refs/heads/master", allRefNames(git2.branchList()
  242. .setListMode(ListMode.ALL).call()));
  243. }
  244. public static String allRefNames(List<Ref> refs) {
  245. StringBuilder sb = new StringBuilder();
  246. for (Ref f : refs) {
  247. if (sb.length() > 0)
  248. sb.append(", ");
  249. sb.append(f.getName());
  250. }
  251. return sb.toString();
  252. }
  253. @Test
  254. public void testCloneRepositoryWhenDestinationDirectoryExistsAndIsNotEmpty()
  255. throws IOException, JGitInternalException, GitAPIException {
  256. String dirName = "testCloneTargetDirectoryNotEmpty";
  257. File directory = createTempDirectory(dirName);
  258. CloneCommand command = Git.cloneRepository();
  259. command.setDirectory(directory);
  260. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  261. Git git2 = command.call();
  262. addRepoToClose(git2.getRepository());
  263. assertNotNull(git2);
  264. // clone again
  265. command = Git.cloneRepository();
  266. command.setDirectory(directory);
  267. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  268. try {
  269. git2 = command.call();
  270. // we shouldn't get here
  271. fail("destination directory already exists and is not an empty folder, cloning should fail");
  272. } catch (JGitInternalException e) {
  273. assertTrue(e.getMessage().contains("not an empty directory"));
  274. assertTrue(e.getMessage().contains(dirName));
  275. }
  276. }
  277. @Test
  278. public void testCloneRepositoryWithMultipleHeadBranches() throws Exception {
  279. git.checkout().setName(Constants.MASTER).call();
  280. git.branchCreate().setName("a").call();
  281. File directory = createTempDirectory("testCloneRepositoryWithMultipleHeadBranches");
  282. CloneCommand clone = Git.cloneRepository();
  283. clone.setDirectory(directory);
  284. clone.setURI("file://" + git.getRepository().getWorkTree().getPath());
  285. Git git2 = clone.call();
  286. addRepoToClose(git2.getRepository());
  287. assertNotNull(git2);
  288. assertEquals(Constants.MASTER, git2.getRepository().getBranch());
  289. }
  290. @Test
  291. public void testCloneRepositoryWithSubmodules() throws Exception {
  292. git.checkout().setName(Constants.MASTER).call();
  293. String file = "file.txt";
  294. writeTrashFile(file, "content");
  295. git.add().addFilepattern(file).call();
  296. RevCommit commit = git.commit().setMessage("create file").call();
  297. SubmoduleAddCommand command = new SubmoduleAddCommand(db);
  298. String path = "sub";
  299. command.setPath(path);
  300. String uri = db.getDirectory().toURI().toString();
  301. command.setURI(uri);
  302. Repository repo = command.call();
  303. assertNotNull(repo);
  304. addRepoToClose(repo);
  305. git.add().addFilepattern(path)
  306. .addFilepattern(Constants.DOT_GIT_MODULES).call();
  307. git.commit().setMessage("adding submodule").call();
  308. File directory = createTempDirectory("testCloneRepositoryWithSubmodules");
  309. CloneCommand clone = Git.cloneRepository();
  310. clone.setDirectory(directory);
  311. clone.setCloneSubmodules(true);
  312. clone.setURI("file://" + git.getRepository().getWorkTree().getPath());
  313. Git git2 = clone.call();
  314. addRepoToClose(git2.getRepository());
  315. assertNotNull(git2);
  316. assertEquals(Constants.MASTER, git2.getRepository().getBranch());
  317. assertTrue(new File(git2.getRepository().getWorkTree(), path
  318. + File.separatorChar + file).exists());
  319. SubmoduleStatusCommand status = new SubmoduleStatusCommand(
  320. git2.getRepository());
  321. Map<String, SubmoduleStatus> statuses = status.call();
  322. SubmoduleStatus pathStatus = statuses.get(path);
  323. assertNotNull(pathStatus);
  324. assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType());
  325. assertEquals(commit, pathStatus.getHeadId());
  326. assertEquals(commit, pathStatus.getIndexId());
  327. }
  328. @Test
  329. public void testCloneRepositoryWithNestedSubmodules() throws Exception {
  330. git.checkout().setName(Constants.MASTER).call();
  331. // Create submodule 1
  332. File submodule1 = createTempDirectory("testCloneRepositoryWithNestedSubmodules1");
  333. Git sub1Git = Git.init().setDirectory(submodule1).call();
  334. assertNotNull(sub1Git);
  335. Repository sub1 = sub1Git.getRepository();
  336. assertNotNull(sub1);
  337. addRepoToClose(sub1);
  338. String file = "file.txt";
  339. String path = "sub";
  340. write(new File(sub1.getWorkTree(), file), "content");
  341. sub1Git.add().addFilepattern(file).call();
  342. RevCommit commit = sub1Git.commit().setMessage("create file").call();
  343. assertNotNull(commit);
  344. // Create submodule 2
  345. File submodule2 = createTempDirectory("testCloneRepositoryWithNestedSubmodules2");
  346. Git sub2Git = Git.init().setDirectory(submodule2).call();
  347. assertNotNull(sub2Git);
  348. Repository sub2 = sub2Git.getRepository();
  349. assertNotNull(sub2);
  350. addRepoToClose(sub2);
  351. write(new File(sub2.getWorkTree(), file), "content");
  352. sub2Git.add().addFilepattern(file).call();
  353. RevCommit sub2Head = sub2Git.commit().setMessage("create file").call();
  354. assertNotNull(sub2Head);
  355. // Add submodule 2 to submodule 1
  356. Repository r = sub1Git.submoduleAdd().setPath(path)
  357. .setURI(sub2.getDirectory().toURI().toString()).call();
  358. assertNotNull(r);
  359. addRepoToClose(r);
  360. RevCommit sub1Head = sub1Git.commit().setAll(true)
  361. .setMessage("Adding submodule").call();
  362. assertNotNull(sub1Head);
  363. // Add submodule 1 to default repository
  364. r = git.submoduleAdd().setPath(path)
  365. .setURI(sub1.getDirectory().toURI().toString()).call();
  366. assertNotNull(r);
  367. addRepoToClose(r);
  368. assertNotNull(git.commit().setAll(true).setMessage("Adding submodule")
  369. .call());
  370. // Clone default repository and include submodules
  371. File directory = createTempDirectory("testCloneRepositoryWithNestedSubmodules");
  372. CloneCommand clone = Git.cloneRepository();
  373. clone.setDirectory(directory);
  374. clone.setCloneSubmodules(true);
  375. clone.setURI(git.getRepository().getDirectory().toURI().toString());
  376. Git git2 = clone.call();
  377. addRepoToClose(git2.getRepository());
  378. assertNotNull(git2);
  379. assertEquals(Constants.MASTER, git2.getRepository().getBranch());
  380. assertTrue(new File(git2.getRepository().getWorkTree(), path
  381. + File.separatorChar + file).exists());
  382. assertTrue(new File(git2.getRepository().getWorkTree(), path
  383. + File.separatorChar + path + File.separatorChar + file)
  384. .exists());
  385. SubmoduleStatusCommand status = new SubmoduleStatusCommand(
  386. git2.getRepository());
  387. Map<String, SubmoduleStatus> statuses = status.call();
  388. SubmoduleStatus pathStatus = statuses.get(path);
  389. assertNotNull(pathStatus);
  390. assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType());
  391. assertEquals(sub1Head, pathStatus.getHeadId());
  392. assertEquals(sub1Head, pathStatus.getIndexId());
  393. SubmoduleWalk walk = SubmoduleWalk.forIndex(git2.getRepository());
  394. assertTrue(walk.next());
  395. Repository clonedSub1 = walk.getRepository();
  396. addRepoToClose(clonedSub1);
  397. assertNotNull(clonedSub1);
  398. status = new SubmoduleStatusCommand(clonedSub1);
  399. statuses = status.call();
  400. pathStatus = statuses.get(path);
  401. assertNotNull(pathStatus);
  402. assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType());
  403. assertEquals(sub2Head, pathStatus.getHeadId());
  404. assertEquals(sub2Head, pathStatus.getIndexId());
  405. assertFalse(walk.next());
  406. }
  407. @Test
  408. public void testCloneWithAutoSetupRebase() throws Exception {
  409. File directory = createTempDirectory("testCloneRepository1");
  410. CloneCommand command = Git.cloneRepository();
  411. command.setDirectory(directory);
  412. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  413. Git git2 = command.call();
  414. addRepoToClose(git2.getRepository());
  415. assertFalse(git2
  416. .getRepository()
  417. .getConfig()
  418. .getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, "test",
  419. ConfigConstants.CONFIG_KEY_REBASE, false));
  420. FileBasedConfig userConfig = SystemReader.getInstance().openUserConfig(
  421. null, git.getRepository().getFS());
  422. userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null,
  423. ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE,
  424. ConfigConstants.CONFIG_KEY_ALWAYS);
  425. userConfig.save();
  426. directory = createTempDirectory("testCloneRepository2");
  427. command = Git.cloneRepository();
  428. command.setDirectory(directory);
  429. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  430. git2 = command.call();
  431. addRepoToClose(git2.getRepository());
  432. assertTrue(git2
  433. .getRepository()
  434. .getConfig()
  435. .getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, "test",
  436. ConfigConstants.CONFIG_KEY_REBASE, false));
  437. userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null,
  438. ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE,
  439. ConfigConstants.CONFIG_KEY_REMOTE);
  440. userConfig.save();
  441. directory = createTempDirectory("testCloneRepository2");
  442. command = Git.cloneRepository();
  443. command.setDirectory(directory);
  444. command.setURI("file://" + git.getRepository().getWorkTree().getPath());
  445. git2 = command.call();
  446. addRepoToClose(git2.getRepository());
  447. assertTrue(git2
  448. .getRepository()
  449. .getConfig()
  450. .getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, "test",
  451. ConfigConstants.CONFIG_KEY_REBASE, false));
  452. }
  453. }