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 testFetchHasRefLogForRemoteRef() throws Exception {
81
82 ObjectId defaultBranchSha1 = remoteGit.commit()
83 .setMessage("initial commit").call().getId();
84
85 git.fetch().setRemote("test")
86 .setRefSpecs("refs/heads/*:refs/remotes/origin/*").call();
87
88 List<Ref> allFetchedRefs = git.getRepository().getRefDatabase()
89 .getRefs();
90 assertEquals(allFetchedRefs.size(), 1);
91 Ref remoteRef = allFetchedRefs.get(0);
92
93 assertTrue(remoteRef.getName().startsWith(Constants.R_REMOTES));
94 assertEquals(defaultBranchSha1, remoteRef.getObjectId());
95 assertNotNull(git.getRepository().getReflogReader(remoteRef.getName())
96 .getLastEntry());
97 }
98
99 @Test
100 public void testForcedFetch() throws Exception {
101 remoteGit.commit().setMessage("commit").call();
102 remoteGit.commit().setMessage("commit2").call();
103 git.fetch().setRemote("test")
104 .setRefSpecs("refs/heads/master:refs/heads/master").call();
105
106 remoteGit.commit().setAmend(true).setMessage("amended").call();
107 FetchResult res = git.fetch().setRemote("test")
108 .setRefSpecs("refs/heads/master:refs/heads/master").call();
109 assertEquals(RefUpdate.Result.REJECTED,
110 res.getTrackingRefUpdate("refs/heads/master").getResult());
111 res = git.fetch().setRemote("test")
112 .setRefSpecs("refs/heads/master:refs/heads/master")
113 .setForceUpdate(true).call();
114 assertEquals(RefUpdate.Result.FORCED,
115 res.getTrackingRefUpdate("refs/heads/master").getResult());
116 }
117
118 @Test
119 public void testFetchSimpleNegativeRefSpec() throws Exception {
120 remoteGit.commit().setMessage("commit").call();
121
122 FetchResult res = git.fetch().setRemote("test")
123 .setRefSpecs("refs/heads/master:refs/heads/test",
124 "^:refs/heads/test")
125 .call();
126 assertNull(res.getTrackingRefUpdate("refs/heads/test"));
127
128 res = git.fetch().setRemote("test")
129 .setRefSpecs("refs/heads/master:refs/heads/test",
130 "^refs/heads/master")
131 .call();
132 assertNull(res.getTrackingRefUpdate("refs/heads/test"));
133 }
134
135 @Test
136 public void negativeRefSpecFilterBySource() throws Exception {
137 remoteGit.commit().setMessage("commit").call();
138 remoteGit.branchCreate().setName("test").call();
139 remoteGit.commit().setMessage("commit1").call();
140 remoteGit.branchCreate().setName("dev").call();
141
142 FetchResult res = git.fetch().setRemote("test")
143 .setRefSpecs("refs/*:refs/origins/*", "^refs/*/test")
144 .call();
145 assertNotNull(res.getTrackingRefUpdate("refs/origins/heads/master"));
146 assertNull(res.getTrackingRefUpdate("refs/origins/heads/test"));
147 assertNotNull(res.getTrackingRefUpdate("refs/origins/heads/dev"));
148 }
149
150 @Test
151 public void negativeRefSpecFilterByDestination() throws Exception {
152 remoteGit.commit().setMessage("commit").call();
153 remoteGit.branchCreate().setName("meta").call();
154 remoteGit.commit().setMessage("commit1").call();
155 remoteGit.branchCreate().setName("data").call();
156
157 FetchResult res = git.fetch().setRemote("test")
158 .setRefSpecs("refs/*:refs/secret/*", "^:refs/secret/*/meta")
159 .call();
160 assertNotNull(res.getTrackingRefUpdate("refs/secret/heads/master"));
161 assertNull(res.getTrackingRefUpdate("refs/secret/heads/meta"));
162 assertNotNull(res.getTrackingRefUpdate("refs/secret/heads/data"));
163 }
164
165 @Test
166 public void fetchAddsBranches() throws Exception {
167 final String branch1 = "b1";
168 final String branch2 = "b2";
169 final String remoteBranch1 = "test/" + branch1;
170 final String remoteBranch2 = "test/" + branch2;
171 remoteGit.commit().setMessage("commit").call();
172 Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
173 remoteGit.commit().setMessage("commit").call();
174 Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
175
176 String spec = "refs/heads/*:refs/remotes/test/*";
177 git.fetch().setRemote("test").setRefSpecs(spec).call();
178 assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
179 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
180 }
181
182 @Test
183 public void fetchDoesntDeleteBranches() throws Exception {
184 final String branch1 = "b1";
185 final String branch2 = "b2";
186 final String remoteBranch1 = "test/" + branch1;
187 final String remoteBranch2 = "test/" + branch2;
188 remoteGit.commit().setMessage("commit").call();
189 Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
190 remoteGit.commit().setMessage("commit").call();
191 Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
192
193 String spec = "refs/heads/*:refs/remotes/test/*";
194 git.fetch().setRemote("test").setRefSpecs(spec).call();
195 assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
196 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
197
198 remoteGit.branchDelete().setBranchNames(branch1).call();
199 git.fetch().setRemote("test").setRefSpecs(spec).call();
200 assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
201 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
202 }
203
204 @Test
205 public void fetchUpdatesBranches() throws Exception {
206 final String branch1 = "b1";
207 final String branch2 = "b2";
208 final String remoteBranch1 = "test/" + branch1;
209 final String remoteBranch2 = "test/" + branch2;
210 remoteGit.commit().setMessage("commit").call();
211 Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
212 remoteGit.commit().setMessage("commit").call();
213 Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
214
215 String spec = "refs/heads/*:refs/remotes/test/*";
216 git.fetch().setRemote("test").setRefSpecs(spec).call();
217 assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
218 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
219
220 remoteGit.commit().setMessage("commit").call();
221 branchRef2 = remoteGit.branchCreate().setName(branch2).setForce(true).call();
222 git.fetch().setRemote("test").setRefSpecs(spec).call();
223 assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
224 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
225 }
226
227 @Test
228 public void fetchPrunesBranches() throws Exception {
229 final String branch1 = "b1";
230 final String branch2 = "b2";
231 final String remoteBranch1 = "test/" + branch1;
232 final String remoteBranch2 = "test/" + branch2;
233 remoteGit.commit().setMessage("commit").call();
234 Ref branchRef1 = remoteGit.branchCreate().setName(branch1).call();
235 remoteGit.commit().setMessage("commit").call();
236 Ref branchRef2 = remoteGit.branchCreate().setName(branch2).call();
237
238 String spec = "refs/heads/*:refs/remotes/test/*";
239 git.fetch().setRemote("test").setRefSpecs(spec).call();
240 assertEquals(branchRef1.getObjectId(), db.resolve(remoteBranch1));
241 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
242
243 remoteGit.branchDelete().setBranchNames(branch1).call();
244 git.fetch().setRemote("test").setRefSpecs(spec)
245 .setRemoveDeletedRefs(true).call();
246 assertNull(db.resolve(remoteBranch1));
247 assertEquals(branchRef2.getObjectId(), db.resolve(remoteBranch2));
248 }
249
250 @Test
251 public void fetchShouldAutoFollowTag() throws Exception {
252 remoteGit.commit().setMessage("commit").call();
253 Ref tagRef = remoteGit.tag().setName("foo").call();
254
255 git.fetch().setRemote("test")
256 .setRefSpecs("refs/heads/*:refs/remotes/origin/*")
257 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
258
259 assertEquals(tagRef.getObjectId(), db.resolve("foo"));
260 }
261
262 @Test
263 public void fetchShouldAutoFollowTagForFetchedObjects() throws Exception {
264 remoteGit.commit().setMessage("commit").call();
265 Ref tagRef = remoteGit.tag().setName("foo").call();
266 remoteGit.commit().setMessage("commit2").call();
267 git.fetch().setRemote("test")
268 .setRefSpecs("refs/heads/*:refs/remotes/origin/*")
269 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
270 assertEquals(tagRef.getObjectId(), db.resolve("foo"));
271 }
272
273 @Test
274 public void fetchShouldNotFetchTagsFromOtherBranches() throws Exception {
275 remoteGit.commit().setMessage("commit").call();
276 remoteGit.checkout().setName("other").setCreateBranch(true).call();
277 remoteGit.commit().setMessage("commit2").call();
278 remoteGit.tag().setName("foo").call();
279 git.fetch().setRemote("test")
280 .setRefSpecs("refs/heads/master:refs/remotes/origin/master")
281 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
282 assertNull(db.resolve("foo"));
283 }
284
285 @Test
286 public void fetchWithUpdatedTagShouldNotTryToUpdateLocal() throws Exception {
287 final String tagName = "foo";
288 remoteGit.commit().setMessage("commit").call();
289 Ref tagRef = remoteGit.tag().setName(tagName).call();
290 ObjectId originalId = tagRef.getObjectId();
291
292 String spec = "refs/heads/*:refs/remotes/origin/*";
293 git.fetch().setRemote("test").setRefSpecs(spec)
294 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
295 assertEquals(originalId, db.resolve(tagName));
296
297 remoteGit.commit().setMessage("commit 2").call();
298 remoteGit.tag().setName(tagName).setForceUpdate(true).call();
299
300 FetchResult result = git.fetch().setRemote("test").setRefSpecs(spec)
301 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
302
303 Collection<TrackingRefUpdate> refUpdates = result
304 .getTrackingRefUpdates();
305 assertEquals(1, refUpdates.size());
306 TrackingRefUpdate update = refUpdates.iterator().next();
307 assertEquals("refs/heads/master", update.getRemoteName());
308
309 assertEquals(originalId, db.resolve(tagName));
310 }
311
312 @Test
313 public void fetchWithExplicitTagsShouldUpdateLocal() throws Exception {
314 final String tagName = "foo";
315 remoteGit.commit().setMessage("commit").call();
316 Ref tagRef1 = remoteGit.tag().setName(tagName).call();
317
318 String spec = "refs/heads/*:refs/remotes/origin/*";
319 git.fetch().setRemote("test").setRefSpecs(spec)
320 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
321 assertEquals(tagRef1.getObjectId(), db.resolve(tagName));
322
323 remoteGit.commit().setMessage("commit 2").call();
324 Ref tagRef2 = remoteGit.tag().setName(tagName).setForceUpdate(true)
325 .call();
326
327 FetchResult result = git.fetch().setRemote("test").setRefSpecs(spec)
328 .setTagOpt(TagOpt.FETCH_TAGS).call();
329 TrackingRefUpdate update = result.getTrackingRefUpdate(Constants.R_TAGS
330 + tagName);
331 assertEquals(RefUpdate.Result.FORCED, update.getResult());
332 assertEquals(tagRef2.getObjectId(), db.resolve(tagName));
333 }
334
335 @Test
336 public void testFetchWithPruneShouldKeepOriginHead() throws Exception {
337
338 commitFile("foo", "foo", "master");
339
340 Git cloned = Git.cloneRepository()
341 .setDirectory(createTempDirectory("testCloneRepository"))
342 .setURI("file://"
343 + git.getRepository().getWorkTree().getAbsolutePath())
344 .call();
345 assertNotNull(cloned);
346 Repository clonedRepo = cloned.getRepository();
347 addRepoToClose(clonedRepo);
348 ObjectId originMasterId = clonedRepo
349 .resolve("refs/remotes/origin/master");
350 assertNotNull("Should have origin/master", originMasterId);
351 assertNotEquals("origin/master should not be zero ID",
352 ObjectId.zeroId(), originMasterId);
353
354
355 ObjectId originHeadId = clonedRepo.resolve("refs/remotes/origin/HEAD");
356 if (originHeadId == null) {
357 JGitTestUtil.write(
358 new File(clonedRepo.getDirectory(),
359 "refs/remotes/origin/HEAD"),
360 "ref: refs/remotes/origin/master\n");
361 originHeadId = clonedRepo.resolve("refs/remotes/origin/HEAD");
362 }
363 assertEquals("Should have origin/HEAD", originMasterId, originHeadId);
364 FetchResult result = cloned.fetch().setRemote("origin")
365 .setRemoveDeletedRefs(true).call();
366 assertTrue("Fetch after clone should be up-to-date",
367 result.getTrackingRefUpdates().isEmpty());
368 assertEquals("origin/master should still exist", originMasterId,
369 clonedRepo.resolve("refs/remotes/origin/master"));
370 assertEquals("origin/HEAD should be unchanged", originHeadId,
371 clonedRepo.resolve("refs/remotes/origin/HEAD"));
372 }
373
374 @Test
375 public void fetchAddRefsWithDuplicateRefspec() throws Exception {
376 final String branchName = "branch";
377 final String remoteBranchName = "test/" + branchName;
378 remoteGit.commit().setMessage("commit").call();
379 Ref branchRef = remoteGit.branchCreate().setName(branchName).call();
380
381 final String spec1 = "+refs/heads/*:refs/remotes/test/*";
382 final String spec2 = "refs/heads/*:refs/remotes/test/*";
383 final StoredConfig config = db.getConfig();
384 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
385 remoteConfig.addFetchRefSpec(new RefSpec(spec1));
386 remoteConfig.addFetchRefSpec(new RefSpec(spec2));
387 remoteConfig.update(config);
388
389 git.fetch().setRemote("test").setRefSpecs(spec1).call();
390 assertEquals(branchRef.getObjectId(), db.resolve(remoteBranchName));
391 }
392
393 @Test
394 public void fetchPruneRefsWithDuplicateRefspec()
395 throws Exception {
396 final String branchName = "branch";
397 final String remoteBranchName = "test/" + branchName;
398 remoteGit.commit().setMessage("commit").call();
399 Ref branchRef = remoteGit.branchCreate().setName(branchName).call();
400
401 final String spec1 = "+refs/heads/*:refs/remotes/test/*";
402 final String spec2 = "refs/heads/*:refs/remotes/test/*";
403 final StoredConfig config = db.getConfig();
404 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
405 remoteConfig.addFetchRefSpec(new RefSpec(spec1));
406 remoteConfig.addFetchRefSpec(new RefSpec(spec2));
407 remoteConfig.update(config);
408
409 git.fetch().setRemote("test").setRefSpecs(spec1).call();
410 assertEquals(branchRef.getObjectId(), db.resolve(remoteBranchName));
411
412 remoteGit.branchDelete().setBranchNames(branchName).call();
413 git.fetch().setRemote("test").setRefSpecs(spec1)
414 .setRemoveDeletedRefs(true).call();
415 assertNull(db.resolve(remoteBranchName));
416 }
417
418 @Test
419 public void fetchUpdateRefsWithDuplicateRefspec() throws Exception {
420 final String tagName = "foo";
421 remoteGit.commit().setMessage("commit").call();
422 Ref tagRef1 = remoteGit.tag().setName(tagName).call();
423 List<RefSpec> refSpecs = new ArrayList<>();
424 refSpecs.add(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
425 refSpecs.add(new RefSpec("+refs/tags/*:refs/tags/*"));
426
427
428
429 git.fetch().setRemote("test").setRefSpecs(refSpecs)
430 .setTagOpt(TagOpt.AUTO_FOLLOW).call();
431 assertEquals(tagRef1.getObjectId(), db.resolve(tagName));
432
433 remoteGit.commit().setMessage("commit 2").call();
434 Ref tagRef2 = remoteGit.tag().setName(tagName).setForceUpdate(true)
435 .call();
436 FetchResult result = git.fetch().setRemote("test").setRefSpecs(refSpecs)
437 .setTagOpt(TagOpt.FETCH_TAGS).call();
438 assertEquals(2, result.getTrackingRefUpdates().size());
439 TrackingRefUpdate update = result
440 .getTrackingRefUpdate(Constants.R_TAGS + tagName);
441 assertEquals(RefUpdate.Result.FORCED, update.getResult());
442 assertEquals(tagRef2.getObjectId(), db.resolve(tagName));
443 }
444 }