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.

FetchCommandTest.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*
  2. * Copyright (C) 2010, 2013 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. import static org.junit.Assert.assertEquals;
  12. import static org.junit.Assert.assertNotEquals;
  13. import static org.junit.Assert.assertNotNull;
  14. import static org.junit.Assert.assertNull;
  15. import static org.junit.Assert.assertTrue;
  16. import java.io.File;
  17. import java.util.ArrayList;
  18. import java.util.Collection;
  19. import java.util.List;
  20. import org.eclipse.jgit.junit.JGitTestUtil;
  21. import org.eclipse.jgit.junit.RepositoryTestCase;
  22. import org.eclipse.jgit.lib.Constants;
  23. import org.eclipse.jgit.lib.ObjectId;
  24. import org.eclipse.jgit.lib.Ref;
  25. import org.eclipse.jgit.lib.RefUpdate;
  26. import org.eclipse.jgit.lib.Repository;
  27. import org.eclipse.jgit.lib.StoredConfig;
  28. import org.eclipse.jgit.revwalk.RevCommit;
  29. import org.eclipse.jgit.transport.FetchResult;
  30. import org.eclipse.jgit.transport.RefSpec;
  31. import org.eclipse.jgit.transport.RemoteConfig;
  32. import org.eclipse.jgit.transport.TagOpt;
  33. import org.eclipse.jgit.transport.TrackingRefUpdate;
  34. import org.eclipse.jgit.transport.URIish;
  35. import org.junit.Before;
  36. import org.junit.Test;
  37. public class FetchCommandTest extends RepositoryTestCase {
  38. private Git git;
  39. private Git remoteGit;
  40. @Before
  41. public void setupRemoteRepository() throws Exception {
  42. git = new Git(db);
  43. // create other repository
  44. Repository remoteRepository = createWorkRepository();
  45. remoteGit = new Git(remoteRepository);
  46. // setup the first repository to fetch from the second repository
  47. final StoredConfig config = db.getConfig();
  48. RemoteConfig remoteConfig = new RemoteConfig(config, "test");
  49. URIish uri = new URIish(remoteRepository.getDirectory().toURI().toURL());
  50. remoteConfig.addURI(uri);
  51. remoteConfig.update(config);
  52. config.save();
  53. }
  54. @Test
  55. public void testFetch() throws Exception {
  56. // create some refs via commits and tag
  57. RevCommit commit = remoteGit.commit().setMessage("initial commit").call();
  58. Ref tagRef = remoteGit.tag().setName("tag").call();
  59. git.fetch().setRemote("test")
  60. .setRefSpecs("refs/heads/master:refs/heads/x").call();
  61. assertEquals(commit.getId(),
  62. db.resolve(commit.getId().getName() + "^{commit}"));
  63. assertEquals(tagRef.getObjectId(),
  64. db.resolve(tagRef.getObjectId().getName()));
  65. }
  66. @Test
  67. public void testForcedFetch() throws Exception {
  68. remoteGit.commit().setMessage("commit").call();
  69. remoteGit.commit().setMessage("commit2").call();
  70. git.fetch().setRemote("test")
  71. .setRefSpecs("refs/heads/master:refs/heads/master").call();
  72. remoteGit.commit().setAmend(true).setMessage("amended").call();
  73. FetchResult res = git.fetch().setRemote("test")
  74. .setRefSpecs("refs/heads/master:refs/heads/master").call();
  75. assertEquals(RefUpdate.Result.REJECTED,
  76. res.getTrackingRefUpdate("refs/heads/master").getResult());
  77. res = git.fetch().setRemote("test")
  78. .setRefSpecs("refs/heads/master:refs/heads/master")
  79. .setForceUpdate(true).call();
  80. assertEquals(RefUpdate.Result.FORCED,
  81. res.getTrackingRefUpdate("refs/heads/master").getResult());
  82. }
  83. @Test
  84. public void fetchAddsBranches() throws Exception {
  85. final String branch1 = "b1";
  86. final String branch2 = "b2";
  87. final String remoteBranch1 = "test/" + branch1;
  88. final String remoteBranch2 = "test/" + branch2;
  89. remoteGit.commit().setMessage("commit").call();
  90. Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
  91. remoteGit.commit().setMessage("commit").call();
  92. Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
  93. String spec = "refs/heads/*:refs/remotes/test/*";
  94. git.fetch().setRemote("test").setRefSpecs(spec).call();
  95. assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
  96. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  97. }
  98. @Test
  99. public void fetchDoesntDeleteBranches() throws Exception {
  100. final String branch1 = "b1";
  101. final String branch2 = "b2";
  102. final String remoteBranch1 = "test/" + branch1;
  103. final String remoteBranch2 = "test/" + branch2;
  104. remoteGit.commit().setMessage("commit").call();
  105. Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
  106. remoteGit.commit().setMessage("commit").call();
  107. Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
  108. String spec = "refs/heads/*:refs/remotes/test/*";
  109. git.fetch().setRemote("test").setRefSpecs(spec).call();
  110. assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
  111. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  112. remoteGit.branchDelete().setBranchNames(branch1).call();
  113. git.fetch().setRemote("test").setRefSpecs(spec).call();
  114. assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
  115. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  116. }
  117. @Test
  118. public void fetchUpdatesBranches() throws Exception {
  119. final String branch1 = "b1";
  120. final String branch2 = "b2";
  121. final String remoteBranch1 = "test/" + branch1;
  122. final String remoteBranch2 = "test/" + branch2;
  123. remoteGit.commit().setMessage("commit").call();
  124. Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
  125. remoteGit.commit().setMessage("commit").call();
  126. Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
  127. String spec = "refs/heads/*:refs/remotes/test/*";
  128. git.fetch().setRemote("test").setRefSpecs(spec).call();
  129. assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
  130. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  131. remoteGit.commit().setMessage("commit").call();
  132. branchRef2 = remoteGit.branchCreate().setName(branch2).setForce(true).call();
  133. git.fetch().setRemote("test").setRefSpecs(spec).call();
  134. assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
  135. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  136. }
  137. @Test
  138. public void fetchPrunesBranches() throws Exception {
  139. final String branch1 = "b1";
  140. final String branch2 = "b2";
  141. final String remoteBranch1 = "test/" + branch1;
  142. final String remoteBranch2 = "test/" + branch2;
  143. remoteGit.commit().setMessage("commit").call();
  144. Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
  145. remoteGit.commit().setMessage("commit").call();
  146. Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
  147. String spec = "refs/heads/*:refs/remotes/test/*";
  148. git.fetch().setRemote("test").setRefSpecs(spec).call();
  149. assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
  150. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  151. remoteGit.branchDelete().setBranchNames(branch1).call();
  152. git.fetch().setRemote("test").setRefSpecs(spec)
  153. .setRemoveDeletedRefs(true).call();
  154. assertNull(db.resolve(remoteBranch1));
  155. assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
  156. }
  157. @Test
  158. public void fetchShouldAutoFollowTag() throws Exception {
  159. remoteGit.commit().setMessage("commit").call();
  160. Ref tagRef = remoteGit.tag().setName("foo").call();
  161. git.fetch().setRemote("test")
  162. .setRefSpecs("refs/heads/*:refs/remotes/origin/*")
  163. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  164. assertEquals(tagRef.getObjectId(), db.resolve("foo"));
  165. }
  166. @Test
  167. public void fetchShouldAutoFollowTagForFetchedObjects() throws Exception {
  168. remoteGit.commit().setMessage("commit").call();
  169. Ref tagRef = remoteGit.tag().setName("foo").call();
  170. remoteGit.commit().setMessage("commit2").call();
  171. git.fetch().setRemote("test")
  172. .setRefSpecs("refs/heads/*:refs/remotes/origin/*")
  173. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  174. assertEquals(tagRef.getObjectId(), db.resolve("foo"));
  175. }
  176. @Test
  177. public void fetchShouldNotFetchTagsFromOtherBranches() throws Exception {
  178. remoteGit.commit().setMessage("commit").call();
  179. remoteGit.checkout().setName("other").setCreateBranch(true).call();
  180. remoteGit.commit().setMessage("commit2").call();
  181. remoteGit.tag().setName("foo").call();
  182. git.fetch().setRemote("test")
  183. .setRefSpecs("refs/heads/master:refs/remotes/origin/master")
  184. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  185. assertNull(db.resolve("foo"));
  186. }
  187. @Test
  188. public void fetchWithUpdatedTagShouldNotTryToUpdateLocal() throws Exception {
  189. final String tagName = "foo";
  190. remoteGit.commit().setMessage("commit").call();
  191. Ref tagRef = remoteGit.tag().setName(tagName).call();
  192. ObjectId originalId = tagRef.getObjectId();
  193. String spec = "refs/heads/*:refs/remotes/origin/*";
  194. git.fetch().setRemote("test").setRefSpecs(spec)
  195. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  196. assertEquals(originalId, db.resolve(tagName));
  197. remoteGit.commit().setMessage("commit 2").call();
  198. remoteGit.tag().setName(tagName).setForceUpdate(true).call();
  199. FetchResult result = git.fetch().setRemote("test").setRefSpecs(spec)
  200. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  201. Collection<TrackingRefUpdate> refUpdates = result
  202. .getTrackingRefUpdates();
  203. assertEquals(1, refUpdates.size());
  204. TrackingRefUpdate update = refUpdates.iterator().next();
  205. assertEquals("refs/heads/master", update.getRemoteName());
  206. assertEquals(originalId, db.resolve(tagName));
  207. }
  208. @Test
  209. public void fetchWithExplicitTagsShouldUpdateLocal() throws Exception {
  210. final String tagName = "foo";
  211. remoteGit.commit().setMessage("commit").call();
  212. Ref tagRef1 = remoteGit.tag().setName(tagName).call();
  213. String spec = "refs/heads/*:refs/remotes/origin/*";
  214. git.fetch().setRemote("test").setRefSpecs(spec)
  215. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  216. assertEquals(tagRef1.getObjectId(), db.resolve(tagName));
  217. remoteGit.commit().setMessage("commit 2").call();
  218. Ref tagRef2 = remoteGit.tag().setName(tagName).setForceUpdate(true)
  219. .call();
  220. FetchResult result = git.fetch().setRemote("test").setRefSpecs(spec)
  221. .setTagOpt(TagOpt.FETCH_TAGS).call();
  222. TrackingRefUpdate update = result.getTrackingRefUpdate(Constants.R_TAGS
  223. + tagName);
  224. assertEquals(RefUpdate.Result.FORCED, update.getResult());
  225. assertEquals(tagRef2.getObjectId(), db.resolve(tagName));
  226. }
  227. @Test
  228. public void testFetchWithPruneShouldKeepOriginHead() throws Exception {
  229. // Create a commit in the test repo.
  230. commitFile("foo", "foo", "master");
  231. // Produce a real clone of the git repo
  232. Git cloned = Git.cloneRepository()
  233. .setDirectory(createTempDirectory("testCloneRepository"))
  234. .setURI("file://"
  235. + git.getRepository().getWorkTree().getAbsolutePath())
  236. .call();
  237. assertNotNull(cloned);
  238. Repository clonedRepo = cloned.getRepository();
  239. addRepoToClose(clonedRepo);
  240. ObjectId originMasterId = clonedRepo
  241. .resolve("refs/remotes/origin/master");
  242. assertNotNull("Should have origin/master", originMasterId);
  243. assertNotEquals("origin/master should not be zero ID",
  244. ObjectId.zeroId(), originMasterId);
  245. // Canonical git creates origin/HEAD; JGit (for now) doesn't. Let's
  246. // pretend we did the clone via command-line git.
  247. ObjectId originHeadId = clonedRepo.resolve("refs/remotes/origin/HEAD");
  248. if (originHeadId == null) {
  249. JGitTestUtil.write(
  250. new File(clonedRepo.getDirectory(),
  251. "refs/remotes/origin/HEAD"),
  252. "ref: refs/remotes/origin/master\n");
  253. originHeadId = clonedRepo.resolve("refs/remotes/origin/HEAD");
  254. }
  255. assertEquals("Should have origin/HEAD", originMasterId, originHeadId);
  256. FetchResult result = cloned.fetch().setRemote("origin")
  257. .setRemoveDeletedRefs(true).call();
  258. assertTrue("Fetch after clone should be up-to-date",
  259. result.getTrackingRefUpdates().isEmpty());
  260. assertEquals("origin/master should still exist", originMasterId,
  261. clonedRepo.resolve("refs/remotes/origin/master"));
  262. assertEquals("origin/HEAD should be unchanged", originHeadId,
  263. clonedRepo.resolve("refs/remotes/origin/HEAD"));
  264. }
  265. @Test
  266. public void fetchAddRefsWithDuplicateRefspec() throws Exception {
  267. final String branchName = "branch";
  268. final String remoteBranchName = "test/" + branchName;
  269. remoteGit.commit().setMessage("commit").call();
  270. Ref branchRef = remoteGit.branchCreate().setName(branchName).call();
  271. final String spec1 = "+refs/heads/*:refs/remotes/test/*";
  272. final String spec2 = "refs/heads/*:refs/remotes/test/*";
  273. final StoredConfig config = db.getConfig();
  274. RemoteConfig remoteConfig = new RemoteConfig(config, "test");
  275. remoteConfig.addFetchRefSpec(new RefSpec(spec1));
  276. remoteConfig.addFetchRefSpec(new RefSpec(spec2));
  277. remoteConfig.update(config);
  278. git.fetch().setRemote("test").setRefSpecs(spec1).call();
  279. assertEquals(branchRef.getObjectId(), db.resolve(remoteBranchName));
  280. }
  281. @Test
  282. public void fetchPruneRefsWithDuplicateRefspec()
  283. throws Exception {
  284. final String branchName = "branch";
  285. final String remoteBranchName = "test/" + branchName;
  286. remoteGit.commit().setMessage("commit").call();
  287. Ref branchRef = remoteGit.branchCreate().setName(branchName).call();
  288. final String spec1 = "+refs/heads/*:refs/remotes/test/*";
  289. final String spec2 = "refs/heads/*:refs/remotes/test/*";
  290. final StoredConfig config = db.getConfig();
  291. RemoteConfig remoteConfig = new RemoteConfig(config, "test");
  292. remoteConfig.addFetchRefSpec(new RefSpec(spec1));
  293. remoteConfig.addFetchRefSpec(new RefSpec(spec2));
  294. remoteConfig.update(config);
  295. git.fetch().setRemote("test").setRefSpecs(spec1).call();
  296. assertEquals(branchRef.getObjectId(), db.resolve(remoteBranchName));
  297. remoteGit.branchDelete().setBranchNames(branchName).call();
  298. git.fetch().setRemote("test").setRefSpecs(spec1)
  299. .setRemoveDeletedRefs(true).call();
  300. assertNull(db.resolve(remoteBranchName));
  301. }
  302. @Test
  303. public void fetchUpdateRefsWithDuplicateRefspec() throws Exception {
  304. final String tagName = "foo";
  305. remoteGit.commit().setMessage("commit").call();
  306. Ref tagRef1 = remoteGit.tag().setName(tagName).call();
  307. List<RefSpec> refSpecs = new ArrayList<>();
  308. refSpecs.add(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
  309. refSpecs.add(new RefSpec("+refs/tags/*:refs/tags/*"));
  310. // Updating tags via the RefSpecs and setting TagOpt.FETCH_TAGS (or
  311. // AUTO_FOLLOW) will result internally in *two* updates for the same
  312. // ref.
  313. git.fetch().setRemote("test").setRefSpecs(refSpecs)
  314. .setTagOpt(TagOpt.AUTO_FOLLOW).call();
  315. assertEquals(tagRef1.getObjectId(), db.resolve(tagName));
  316. remoteGit.commit().setMessage("commit 2").call();
  317. Ref tagRef2 = remoteGit.tag().setName(tagName).setForceUpdate(true)
  318. .call();
  319. FetchResult result = git.fetch().setRemote("test").setRefSpecs(refSpecs)
  320. .setTagOpt(TagOpt.FETCH_TAGS).call();
  321. assertEquals(2, result.getTrackingRefUpdates().size());
  322. TrackingRefUpdate update = result
  323. .getTrackingRefUpdate(Constants.R_TAGS + tagName);
  324. assertEquals(RefUpdate.Result.FORCED, update.getResult());
  325. assertEquals(tagRef2.getObjectId(), db.resolve(tagName));
  326. }
  327. }