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 try (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
141 @Test
142 public void testCreateAndList() throws Exception {
143 int localBefore;
144 int remoteBefore;
145 int allBefore;
146
147
148 try {
149 git.branchCreate().setName("In va lid").call();
150 fail("Create branch with invalid ref name should fail");
151 } catch (InvalidRefNameException e) {
152
153 }
154
155 try {
156 git.branchCreate().setName("master").call();
157 fail("Create branch with existing ref name should fail");
158 } catch (RefAlreadyExistsException e) {
159
160 }
161
162 localBefore = git.branchList().call().size();
163 remoteBefore = git.branchList().setListMode(ListMode.REMOTE).call()
164 .size();
165 allBefore = git.branchList().setListMode(ListMode.ALL).call().size();
166
167 assertEquals(localBefore + remoteBefore, allBefore);
168 Ref newBranch = createBranch(git, "NewForTestList", false, "master",
169 null);
170 assertEquals("refs/heads/NewForTestList", newBranch.getName());
171
172 assertEquals(1, git.branchList().call().size() - localBefore);
173 assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
174 .size()
175 - remoteBefore);
176 assertEquals(1, git.branchList().setListMode(ListMode.ALL).call()
177 .size()
178 - allBefore);
179
180 newBranch = createBranch(git,
181 "refs/remotes/origin/NewRemoteForTestList", false, "master",
182 null);
183 assertEquals("refs/heads/refs/remotes/origin/NewRemoteForTestList",
184 newBranch.getName());
185 assertEquals(2, git.branchList().call().size() - localBefore);
186 assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
187 .size()
188 - remoteBefore);
189 assertEquals(2, git.branchList().setListMode(ListMode.ALL).call()
190 .size()
191 - allBefore);
192 }
193
194 @Test(expected = InvalidRefNameException.class)
195 public void testInvalidBranchHEAD() throws Exception {
196 git.branchCreate().setName("HEAD").call();
197 fail("Create branch with invalid ref name should fail");
198 }
199
200 @Test(expected = InvalidRefNameException.class)
201 public void testInvalidBranchDash() throws Exception {
202 git.branchCreate().setName("-x").call();
203 fail("Create branch with invalid ref name should fail");
204 }
205
206 @Test
207 public void testListAllBranchesShouldNotDie() throws Exception {
208 setUpRepoWithRemote().branchList().setListMode(ListMode.ALL).call();
209 }
210
211 @Test
212 public void testListBranchesWithContains() throws Exception {
213 git.branchCreate().setName("foo").setStartPoint(secondCommit).call();
214
215 List<Ref> refs = git.branchList().call();
216 assertEquals(2, refs.size());
217
218 List<Ref> refsContainingSecond = git.branchList()
219 .setContains(secondCommit.name()).call();
220 assertEquals(1, refsContainingSecond.size());
221
222 assertEquals("refs/heads/foo", refsContainingSecond.get(0).getName());
223 }
224
225 @Test
226 public void testCreateFromCommit() throws Exception {
227 Ref branch = git.branchCreate().setName("FromInitial").setStartPoint(
228 initialCommit).call();
229 assertEquals(initialCommit.getId(), branch.getObjectId());
230 branch = git.branchCreate().setName("FromInitial2").setStartPoint(
231 initialCommit.getId().name()).call();
232 assertEquals(initialCommit.getId(), branch.getObjectId());
233 try {
234 git.branchCreate().setName("FromInitial").setStartPoint(
235 secondCommit).call();
236 } catch (RefAlreadyExistsException e) {
237
238 }
239 branch = git.branchCreate().setName("FromInitial").setStartPoint(
240 secondCommit).setForce(true).call();
241 assertEquals(secondCommit.getId(), branch.getObjectId());
242 }
243
244 @Test
245 public void testCreateForce() throws Exception {
246
247 Ref newBranch = createBranch(git, "NewForce", false, secondCommit
248 .getId().name(), null);
249 assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
250 try {
251 newBranch = createBranch(git, "NewForce", false, initialCommit
252 .getId().name(), null);
253 fail("Should have failed");
254 } catch (RefAlreadyExistsException e) {
255
256 }
257 newBranch = createBranch(git, "NewForce", true, initialCommit.getId()
258 .name(), null);
259 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
260 git.branchDelete().setBranchNames("NewForce").call();
261
262
263 git.branchCreate().setName("NewForce").setStartPoint("master").call();
264 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
265 try {
266 git.branchCreate().setName("NewForce").setStartPoint("master")
267 .call();
268 fail("Should have failed");
269 } catch (RefAlreadyExistsException e) {
270
271 }
272 git.branchCreate().setName("NewForce").setStartPoint("master")
273 .setForce(true).call();
274 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
275 }
276
277 @Test
278 public void testCreateFromLightweightTag() throws Exception {
279 RefUpdate rup = db.updateRef("refs/tags/V10");
280 rup.setNewObjectId(initialCommit);
281 rup.setExpectedOldObjectId(ObjectId.zeroId());
282 rup.update();
283
284 Ref branch = git.branchCreate().setName("FromLightweightTag")
285 .setStartPoint("refs/tags/V10").call();
286 assertEquals(initialCommit.getId(), branch.getObjectId());
287
288 }
289
290 @Test
291 public void testCreateFromAnnotatetdTag() throws Exception {
292 Ref tagRef = git.tag().setName("V10").setObjectId(secondCommit).call();
293 Ref branch = git.branchCreate().setName("FromAnnotatedTag")
294 .setStartPoint("refs/tags/V10").call();
295 assertFalse(tagRef.getObjectId().equals(branch.getObjectId()));
296 assertEquals(secondCommit.getId(), branch.getObjectId());
297 }
298
299 @Test
300 public void testDelete() throws Exception {
301 createBranch(git, "ForDelete", false, "master", null);
302 git.branchDelete().setBranchNames("ForDelete").call();
303
304 createBranch(git, "ForDelete", false, secondCommit.getId().name(), null);
305 try {
306 git.branchDelete().setBranchNames("ForDelete").call();
307 fail("Deletion of a non-merged branch without force should have failed");
308 } catch (NotMergedException e) {
309
310 }
311 List<String> deleted = git.branchDelete().setBranchNames("ForDelete")
312 .setForce(true).call();
313 assertEquals(1, deleted.size());
314 assertEquals(Constants.R_HEADS + "ForDelete", deleted.get(0));
315 createBranch(git, "ForDelete", false, "master", null);
316 try {
317 createBranch(git, "ForDelete", false, "master", null);
318 fail("Repeated creation of same branch without force should fail");
319 } catch (RefAlreadyExistsException e) {
320
321 }
322
323 Ref newBranch = createBranch(git, "ForDelete", true, initialCommit
324 .name(), null);
325 assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
326 newBranch = createBranch(git, "ForDelete", true, secondCommit.name(),
327 null);
328 assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
329 git.branchDelete().setBranchNames("ForDelete").setForce(true);
330 try {
331 git.branchDelete().setBranchNames("master").call();
332 fail("Deletion of checked out branch without force should have failed");
333 } catch (CannotDeleteCurrentBranchException e) {
334
335 }
336 try {
337 git.branchDelete().setBranchNames("master").setForce(true).call();
338 fail("Deletion of checked out branch with force should have failed");
339 } catch (CannotDeleteCurrentBranchException e) {
340
341 }
342 }
343
344 @Test
345 public void testPullConfigRemoteBranch() throws Exception {
346 Git localGit = setUpRepoWithRemote();
347 Ref remote = localGit.branchList().setListMode(ListMode.REMOTE).call()
348 .get(0);
349 assertEquals("refs/remotes/origin/master", remote.getName());
350
351 createBranch(localGit, "newFromRemote", false, remote.getName(), null);
352 assertEquals("origin", localGit.getRepository().getConfig().getString(
353 "branch", "newFromRemote", "remote"));
354 localGit.branchDelete().setBranchNames("newFromRemote").call();
355
356 assertNull(localGit.getRepository().getConfig().getString("branch",
357 "newFromRemote", "remote"));
358
359 createBranch(localGit, "newFromRemote", false, remote.getName(), null);
360 assertEquals("origin", localGit.getRepository().getConfig().getString(
361 "branch", "newFromRemote", "remote"));
362 localGit.branchDelete().setBranchNames("refs/heads/newFromRemote")
363 .call();
364
365 assertNull(localGit.getRepository().getConfig().getString("branch",
366 "newFromRemote", "remote"));
367
368
369 createBranch(localGit, "newFromRemote", false, remote.getName(),
370 SetupUpstreamMode.NOTRACK);
371 assertNull(localGit.getRepository().getConfig().getString("branch",
372 "newFromRemote", "remote"));
373 localGit.branchDelete().setBranchNames("newFromRemote").call();
374 }
375
376 @Test
377 public void testPullConfigLocalBranch() throws Exception {
378 Git localGit = setUpRepoWithRemote();
379
380 createBranch(localGit, "newFromMaster", false, "master", null);
381 assertNull(localGit.getRepository().getConfig().getString("branch",
382 "newFromMaster", "remote"));
383 localGit.branchDelete().setBranchNames("newFromMaster").call();
384
385 createBranch(localGit, "newFromMaster", false, "master",
386 SetupUpstreamMode.TRACK);
387 assertEquals(".", localGit.getRepository().getConfig().getString(
388 "branch", "newFromMaster", "remote"));
389 localGit.branchDelete().setBranchNames("refs/heads/newFromMaster")
390 .call();
391
392 assertNull(localGit.getRepository().getConfig().getString("branch",
393 "newFromRemote", "remote"));
394 }
395
396 @Test
397 public void testPullConfigRenameLocalBranch() throws Exception {
398 Git localGit = setUpRepoWithRemote();
399
400 createBranch(localGit, "newFromMaster", false, "master", null);
401 assertNull(localGit.getRepository().getConfig().getString("branch",
402 "newFromMaster", "remote"));
403 localGit.branchDelete().setBranchNames("newFromMaster").call();
404
405 createBranch(localGit, "newFromMaster", false, "master",
406 SetupUpstreamMode.TRACK);
407 assertEquals(".", localGit.getRepository().getConfig().getString(
408 "branch", "newFromMaster", "remote"));
409 localGit.branchRename().setOldName("newFromMaster").setNewName(
410 "renamed").call();
411 assertNull(".", localGit.getRepository().getConfig().getString(
412 "branch", "newFromMaster", "remote"));
413 assertEquals(".", localGit.getRepository().getConfig().getString(
414 "branch", "renamed", "remote"));
415 localGit.branchDelete().setBranchNames("renamed").call();
416
417 assertNull(localGit.getRepository().getConfig().getString("branch",
418 "newFromRemote", "remote"));
419 }
420
421 @Test
422 public void testRenameLocalBranch() throws Exception {
423
424 try {
425 git.branchRename().call();
426 } catch (InvalidRefNameException e) {
427
428 }
429
430 try {
431 git.branchRename().setNewName("In va lid").call();
432 } catch (InvalidRefNameException e) {
433
434 }
435
436 try {
437 git.branchRename().setOldName("notexistingbranch").setNewName(
438 "newname").call();
439 } catch (RefNotFoundException e) {
440
441 }
442
443 createBranch(git, "existing", false, "master", null);
444
445 Ref branch = createBranch(git, "fromMasterForRename", false, "master",
446 null);
447 assertEquals(Constants.R_HEADS + "fromMasterForRename", branch
448 .getName());
449 Ref renamed = git.branchRename().setOldName("fromMasterForRename")
450 .setNewName("newName").call();
451 assertEquals(Constants.R_HEADS + "newName", renamed.getName());
452 try {
453 git.branchRename().setOldName(renamed.getName()).setNewName(
454 "existing").call();
455 fail("Should have failed");
456 } catch (RefAlreadyExistsException e) {
457
458 }
459 try {
460 git.branchRename().setNewName("In va lid").call();
461 fail("Rename with invalid ref name should fail");
462 } catch (InvalidRefNameException e) {
463
464 }
465
466 RefUpdate rup = git.getRepository().updateRef(Constants.HEAD, true);
467 rup.setNewObjectId(initialCommit);
468 rup.forceUpdate();
469 try {
470 git.branchRename().setNewName("detached").call();
471 } catch (DetachedHeadException e) {
472
473 }
474 }
475
476 @Test
477 public void testRenameRemoteTrackingBranch() throws Exception {
478 Git localGit = setUpRepoWithRemote();
479 Ref remoteBranch = localGit.branchList().setListMode(ListMode.REMOTE)
480 .call().get(0);
481 Ref renamed = localGit.branchRename()
482 .setOldName(remoteBranch.getName()).setNewName("newRemote")
483 .call();
484 assertEquals(Constants.R_REMOTES + "newRemote", renamed.getName());
485 }
486
487 @Test
488 public void testCreationImplicitStart() throws Exception {
489 git.branchCreate().setName("topic").call();
490 assertEquals(db.resolve("HEAD"), db.resolve("topic"));
491 }
492
493 @Test
494 public void testCreationNullStartPoint() throws Exception {
495 String startPoint = null;
496 git.branchCreate().setName("topic").setStartPoint(startPoint).call();
497 assertEquals(db.resolve("HEAD"), db.resolve("topic"));
498 }
499
500 public Ref createBranch(Git actGit, String name, boolean force,
501 String startPoint, SetupUpstreamMode mode)
502 throws JGitInternalException, GitAPIException {
503 CreateBranchCommand cmd = actGit.branchCreate();
504 cmd.setName(name);
505 cmd.setForce(force);
506 cmd.setStartPoint(startPoint);
507 cmd.setUpstreamMode(mode);
508 return cmd.call();
509 }
510 }