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