1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.api;
44
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertFalse;
47 import static org.junit.Assert.assertNull;
48 import static org.junit.Assert.fail;
49
50 import java.util.List;
51
52 import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
53 import org.eclipse.jgit.api.ListBranchCommand.ListMode;
54 import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
55 import org.eclipse.jgit.api.errors.DetachedHeadException;
56 import org.eclipse.jgit.api.errors.GitAPIException;
57 import org.eclipse.jgit.api.errors.InvalidRefNameException;
58 import org.eclipse.jgit.api.errors.JGitInternalException;
59 import org.eclipse.jgit.api.errors.NotMergedException;
60 import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
61 import org.eclipse.jgit.api.errors.RefNotFoundException;
62 import org.eclipse.jgit.junit.RepositoryTestCase;
63 import org.eclipse.jgit.lib.Constants;
64 import org.eclipse.jgit.lib.ObjectId;
65 import org.eclipse.jgit.lib.Ref;
66 import org.eclipse.jgit.lib.RefUpdate;
67 import org.eclipse.jgit.lib.Repository;
68 import org.eclipse.jgit.lib.StoredConfig;
69 import org.eclipse.jgit.revwalk.RevCommit;
70 import org.eclipse.jgit.transport.FetchResult;
71 import org.eclipse.jgit.transport.RefSpec;
72 import org.eclipse.jgit.transport.RemoteConfig;
73 import org.eclipse.jgit.transport.URIish;
74 import org.junit.Before;
75 import org.junit.Test;
76
77 public class BranchCommandTest extends RepositoryTestCase {
78 private Git git;
79
80 RevCommit initialCommit;
81
82 RevCommit secondCommit;
83
84 @Override
85 @Before
86 public void setUp() throws Exception {
87 super.setUp();
88 git = new Git(db);
89
90 git.commit().setMessage("initial commit").call();
91
92 writeTrashFile("Test.txt", "Hello world");
93 git.add().addFilepattern("Test.txt").call();
94 initialCommit = git.commit().setMessage("Initial commit").call();
95 writeTrashFile("Test.txt", "Some change");
96 git.add().addFilepattern("Test.txt").call();
97 secondCommit = git.commit().setMessage("Second commit").call();
98
99 RefUpdate rup = db.updateRef("refs/heads/master");
100 rup.setNewObjectId(initialCommit.getId());
101 rup.setForceUpdate(true);
102 rup.update();
103 }
104
105 private Git setUpRepoWithRemote() throws Exception {
106 Repository remoteRepository = createWorkRepository();
107 Git remoteGit = new Git(remoteRepository);
108
109 writeTrashFile("Test.txt", "Hello world");
110 remoteGit.add().addFilepattern("Test.txt").call();
111 initialCommit = remoteGit.commit().setMessage("Initial commit").call();
112 writeTrashFile("Test.txt", "Some change");
113 remoteGit.add().addFilepattern("Test.txt").call();
114 secondCommit = remoteGit.commit().setMessage("Second commit").call();
115
116 RefUpdate rup = remoteRepository.updateRef("refs/heads/master");
117 rup.setNewObjectId(initialCommit.getId());
118 rup.forceUpdate();
119
120 Repository localRepository = createWorkRepository();
121 Git localGit = new Git(localRepository);
122 StoredConfig config = localRepository.getConfig();
123 RemoteConfig rc = new RemoteConfig(config, "origin");
124 rc.addURI(new URIish(remoteRepository.getDirectory().getAbsolutePath()));
125 rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
126 rc.update(config);
127 config.save();
128 FetchResult res = localGit.fetch().setRemote("origin").call();
129 assertFalse(res.getTrackingRefUpdates().isEmpty());
130 rup = localRepository.updateRef("refs/heads/master");
131 rup.setNewObjectId(initialCommit.getId());
132 rup.forceUpdate();
133 rup = localRepository.updateRef(Constants.HEAD);
134 rup.link("refs/heads/master");
135 rup.setNewObjectId(initialCommit.getId());
136 rup.update();
137 return localGit;
138 }
139
140 @Test
141 public void testCreateAndList() throws Exception {
142 int localBefore;
143 int remoteBefore;
144 int allBefore;
145
146
147 try {
148 git.branchCreate().setName("In va lid").call();
149 fail("Create branch with invalid ref name should fail");
150 } catch (InvalidRefNameException e) {
151
152 }
153
154 try {
155 git.branchCreate().setName("master").call();
156 fail("Create branch with existing ref name should fail");
157 } catch (RefAlreadyExistsException e) {
158
159 }
160
161 localBefore = git.branchList().call().size();
162 remoteBefore = git.branchList().setListMode(ListMode.REMOTE).call()
163 .size();
164 allBefore = git.branchList().setListMode(ListMode.ALL).call().size();
165
166 assertEquals(localBefore + remoteBefore, allBefore);
167 Ref newBranch = createBranch(git, "NewForTestList", false, "master",
168 null);
169 assertEquals("refs/heads/NewForTestList", newBranch.getName());
170
171 assertEquals(1, git.branchList().call().size() - localBefore);
172 assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
173 .size()
174 - remoteBefore);
175 assertEquals(1, git.branchList().setListMode(ListMode.ALL).call()
176 .size()
177 - allBefore);
178
179 newBranch = createBranch(git,
180 "refs/remotes/origin/NewRemoteForTestList", false, "master",
181 null);
182 assertEquals("refs/heads/refs/remotes/origin/NewRemoteForTestList",
183 newBranch.getName());
184 assertEquals(2, git.branchList().call().size() - localBefore);
185 assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
186 .size()
187 - remoteBefore);
188 assertEquals(2, git.branchList().setListMode(ListMode.ALL).call()
189 .size()
190 - allBefore);
191 }
192
193 @Test
194 public void testListAllBranchesShouldNotDie() throws Exception {
195 Git git = setUpRepoWithRemote();
196 git.branchList().setListMode(ListMode.ALL).call();
197 }
198
199 @Test
200 public void testListBranchesWithContains() throws Exception {
201 git.branchCreate().setName("foo").setStartPoint(secondCommit).call();
202
203 List<Ref> refs = git.branchList().call();
204 assertEquals(2, refs.size());
205
206 List<Ref> refsContainingSecond = git.branchList()
207 .setContains(secondCommit.name()).call();
208 assertEquals(1, refsContainingSecond.size());
209
210 assertEquals("refs/heads/foo", refsContainingSecond.get(0).getName());
211 }
212
213 @Test
214 public void testCreateFromCommit() throws Exception {
215 Ref branch = git.branchCreate().setName("FromInitial").setStartPoint(
216 initialCommit).call();
217 assertEquals(initialCommit.getId(), branch.getObjectId());
218 branch = git.branchCreate().setName("FromInitial2").setStartPoint(
219 initialCommit.getId().name()).call();
220 assertEquals(initialCommit.getId(), branch.getObjectId());
221 try {
222 git.branchCreate().setName("FromInitial").setStartPoint(
223 secondCommit).call();
224 } catch (RefAlreadyExistsException e) {
225
226 }
227 branch = git.branchCreate().setName("FromInitial").setStartPoint(
228 secondCommit).setForce(true).call();
229 assertEquals(secondCommit.getId(), branch.getObjectId());
230 }
231
232 @Test
233 public void testCreateForce() throws Exception {
234
235 Ref newBranch = createBranch(git, "NewForce", false, secondCommit
236 .getId().name(), null);
237 assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
238 try {
239 newBranch = createBranch(git, "NewForce", false, initialCommit
240 .getId().name(), null);
241 fail("Should have failed");
242 } catch (RefAlreadyExistsException e) {
243
244 }
245 newBranch = createBranch(git, "NewForce", true, initialCommit.getId()
246 .name(), null);
247 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
248 git.branchDelete().setBranchNames("NewForce").call();
249
250
251 git.branchCreate().setName("NewForce").setStartPoint("master").call();
252 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
253 try {
254 git.branchCreate().setName("NewForce").setStartPoint("master")
255 .call();
256 fail("Should have failed");
257 } catch (RefAlreadyExistsException e) {
258
259 }
260 git.branchCreate().setName("NewForce").setStartPoint("master")
261 .setForce(true).call();
262 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
263 }
264
265 @Test
266 public void testCreateFromLightweightTag() throws Exception {
267 RefUpdate rup = db.updateRef("refs/tags/V10");
268 rup.setNewObjectId(initialCommit);
269 rup.setExpectedOldObjectId(ObjectId.zeroId());
270 rup.update();
271
272 Ref branch = git.branchCreate().setName("FromLightweightTag")
273 .setStartPoint("refs/tags/V10").call();
274 assertEquals(initialCommit.getId(), branch.getObjectId());
275
276 }
277
278 @Test
279 public void testCreateFromAnnotatetdTag() throws Exception {
280 Ref tagRef = git.tag().setName("V10").setObjectId(secondCommit).call();
281 Ref branch = git.branchCreate().setName("FromAnnotatedTag")
282 .setStartPoint("refs/tags/V10").call();
283 assertFalse(tagRef.getObjectId().equals(branch.getObjectId()));
284 assertEquals(secondCommit.getId(), branch.getObjectId());
285 }
286
287 @Test
288 public void testDelete() throws Exception {
289 createBranch(git, "ForDelete", false, "master", null);
290 git.branchDelete().setBranchNames("ForDelete").call();
291
292 createBranch(git, "ForDelete", false, secondCommit.getId().name(), null);
293 try {
294 git.branchDelete().setBranchNames("ForDelete").call();
295 fail("Deletion of a non-merged branch without force should have failed");
296 } catch (NotMergedException e) {
297
298 }
299 List<String> deleted = git.branchDelete().setBranchNames("ForDelete")
300 .setForce(true).call();
301 assertEquals(1, deleted.size());
302 assertEquals(Constants.R_HEADS + "ForDelete", deleted.get(0));
303 createBranch(git, "ForDelete", false, "master", null);
304 try {
305 createBranch(git, "ForDelete", false, "master", null);
306 fail("Repeated creation of same branch without force should fail");
307 } catch (RefAlreadyExistsException e) {
308
309 }
310
311 Ref newBranch = createBranch(git, "ForDelete", true, initialCommit
312 .name(), null);
313 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
314 newBranch = createBranch(git, "ForDelete", true, secondCommit.name(),
315 null);
316 assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
317 git.branchDelete().setBranchNames("ForDelete").setForce(true);
318 try {
319 git.branchDelete().setBranchNames("master").call();
320 fail("Deletion of checked out branch without force should have failed");
321 } catch (CannotDeleteCurrentBranchException e) {
322
323 }
324 try {
325 git.branchDelete().setBranchNames("master").setForce(true).call();
326 fail("Deletion of checked out branch with force should have failed");
327 } catch (CannotDeleteCurrentBranchException e) {
328
329 }
330 }
331
332 @Test
333 public void testPullConfigRemoteBranch() throws Exception {
334 Git localGit = setUpRepoWithRemote();
335 Ref remote = localGit.branchList().setListMode(ListMode.REMOTE).call()
336 .get(0);
337 assertEquals("refs/remotes/origin/master", remote.getName());
338
339 createBranch(localGit, "newFromRemote", false, remote.getName(), null);
340 assertEquals("origin", localGit.getRepository().getConfig().getString(
341 "branch", "newFromRemote", "remote"));
342 localGit.branchDelete().setBranchNames("newFromRemote").call();
343
344 assertNull(localGit.getRepository().getConfig().getString("branch",
345 "newFromRemote", "remote"));
346
347 createBranch(localGit, "newFromRemote", false, remote.getName(), null);
348 assertEquals("origin", localGit.getRepository().getConfig().getString(
349 "branch", "newFromRemote", "remote"));
350 localGit.branchDelete().setBranchNames("refs/heads/newFromRemote")
351 .call();
352
353 assertNull(localGit.getRepository().getConfig().getString("branch",
354 "newFromRemote", "remote"));
355
356
357 createBranch(localGit, "newFromRemote", false, remote.getName(),
358 SetupUpstreamMode.NOTRACK);
359 assertNull(localGit.getRepository().getConfig().getString("branch",
360 "newFromRemote", "remote"));
361 localGit.branchDelete().setBranchNames("newFromRemote").call();
362 }
363
364 @Test
365 public void testPullConfigLocalBranch() throws Exception {
366 Git localGit = setUpRepoWithRemote();
367
368 createBranch(localGit, "newFromMaster", false, "master", null);
369 assertNull(localGit.getRepository().getConfig().getString("branch",
370 "newFromMaster", "remote"));
371 localGit.branchDelete().setBranchNames("newFromMaster").call();
372
373 createBranch(localGit, "newFromMaster", false, "master",
374 SetupUpstreamMode.TRACK);
375 assertEquals(".", localGit.getRepository().getConfig().getString(
376 "branch", "newFromMaster", "remote"));
377 localGit.branchDelete().setBranchNames("refs/heads/newFromMaster")
378 .call();
379
380 assertNull(localGit.getRepository().getConfig().getString("branch",
381 "newFromRemote", "remote"));
382 }
383
384 @Test
385 public void testPullConfigRenameLocalBranch() throws Exception {
386 Git localGit = setUpRepoWithRemote();
387
388 createBranch(localGit, "newFromMaster", false, "master", null);
389 assertNull(localGit.getRepository().getConfig().getString("branch",
390 "newFromMaster", "remote"));
391 localGit.branchDelete().setBranchNames("newFromMaster").call();
392
393 createBranch(localGit, "newFromMaster", false, "master",
394 SetupUpstreamMode.TRACK);
395 assertEquals(".", localGit.getRepository().getConfig().getString(
396 "branch", "newFromMaster", "remote"));
397 localGit.branchRename().setOldName("newFromMaster").setNewName(
398 "renamed").call();
399 assertNull(".", localGit.getRepository().getConfig().getString(
400 "branch", "newFromMaster", "remote"));
401 assertEquals(".", localGit.getRepository().getConfig().getString(
402 "branch", "renamed", "remote"));
403 localGit.branchDelete().setBranchNames("renamed").call();
404
405 assertNull(localGit.getRepository().getConfig().getString("branch",
406 "newFromRemote", "remote"));
407 }
408
409 @Test
410 public void testRenameLocalBranch() throws Exception {
411
412 try {
413 git.branchRename().call();
414 } catch (InvalidRefNameException e) {
415
416 }
417
418 try {
419 git.branchRename().setNewName("In va lid").call();
420 } catch (InvalidRefNameException e) {
421
422 }
423
424 try {
425 git.branchRename().setOldName("notexistingbranch").setNewName(
426 "newname").call();
427 } catch (RefNotFoundException e) {
428
429 }
430
431 createBranch(git, "existing", false, "master", null);
432
433 Ref branch = createBranch(git, "fromMasterForRename", false, "master",
434 null);
435 assertEquals(Constants.R_HEADS + "fromMasterForRename", branch
436 .getName());
437 Ref renamed = git.branchRename().setOldName("fromMasterForRename")
438 .setNewName("newName").call();
439 assertEquals(Constants.R_HEADS + "newName", renamed.getName());
440 try {
441 git.branchRename().setOldName(renamed.getName()).setNewName(
442 "existing").call();
443 fail("Should have failed");
444 } catch (RefAlreadyExistsException e) {
445
446 }
447 try {
448 git.branchRename().setNewName("In va lid").call();
449 fail("Rename with invalid ref name should fail");
450 } catch (InvalidRefNameException e) {
451
452 }
453
454 RefUpdate rup = git.getRepository().updateRef(Constants.HEAD, true);
455 rup.setNewObjectId(initialCommit);
456 rup.forceUpdate();
457 try {
458 git.branchRename().setNewName("detached").call();
459 } catch (DetachedHeadException e) {
460
461 }
462 }
463
464 @Test
465 public void testRenameRemoteTrackingBranch() throws Exception {
466 Git localGit = setUpRepoWithRemote();
467 Ref remoteBranch = localGit.branchList().setListMode(ListMode.REMOTE)
468 .call().get(0);
469 Ref renamed = localGit.branchRename()
470 .setOldName(remoteBranch.getName()).setNewName("newRemote")
471 .call();
472 assertEquals(Constants.R_REMOTES + "newRemote", renamed.getName());
473 }
474
475 @Test
476 public void testCreationImplicitStart() throws Exception {
477 git.branchCreate().setName("topic").call();
478 assertEquals(db.resolve("HEAD"), db.resolve("topic"));
479 }
480
481 @Test
482 public void testCreationNullStartPoint() throws Exception {
483 String startPoint = null;
484 git.branchCreate().setName("topic").setStartPoint(startPoint).call();
485 assertEquals(db.resolve("HEAD"), db.resolve("topic"));
486 }
487
488 public Ref createBranch(Git actGit, String name, boolean force,
489 String startPoint, SetupUpstreamMode mode)
490 throws JGitInternalException, GitAPIException {
491 CreateBranchCommand cmd = actGit.branchCreate();
492 cmd.setName(name);
493 cmd.setForce(force);
494 cmd.setStartPoint(startPoint);
495 cmd.setUpstreamMode(mode);
496 return cmd.call();
497 }
498 }