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