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
44
45
46 package org.eclipse.jgit.internal.storage.file;
47
48 import static java.nio.charset.StandardCharsets.UTF_8;
49 import static org.eclipse.jgit.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertEquals;
51 import static org.junit.Assert.assertFalse;
52 import static org.junit.Assert.assertNotNull;
53 import static org.junit.Assert.assertNotSame;
54 import static org.junit.Assert.assertNull;
55 import static org.junit.Assert.assertSame;
56 import static org.junit.Assert.assertTrue;
57 import static org.junit.Assert.fail;
58
59 import java.io.File;
60 import java.io.IOException;
61 import java.util.List;
62 import java.util.Map;
63 import java.util.Map.Entry;
64
65 import org.eclipse.jgit.lib.AnyObjectId;
66 import org.eclipse.jgit.lib.Constants;
67 import org.eclipse.jgit.lib.ObjectId;
68 import org.eclipse.jgit.lib.ObjectInserter;
69 import org.eclipse.jgit.lib.PersonIdent;
70 import org.eclipse.jgit.lib.Ref;
71 import org.eclipse.jgit.lib.RefRename;
72 import org.eclipse.jgit.lib.RefUpdate;
73 import org.eclipse.jgit.lib.RefUpdate.Result;
74 import org.eclipse.jgit.lib.ReflogEntry;
75 import org.eclipse.jgit.lib.ReflogReader;
76 import org.eclipse.jgit.lib.Repository;
77 import org.eclipse.jgit.revwalk.RevCommit;
78 import org.eclipse.jgit.revwalk.RevWalk;
79 import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
80 import org.junit.Test;
81
82 public class RefUpdateTest extends SampleDataRepositoryTestCase {
83
84 private void writeSymref(String src, String dst) throws IOException {
85 RefUpdate u = db.updateRef(src);
86 switch (u.link(dst)) {
87 case NEW:
88 case FORCED:
89 case NO_CHANGE:
90 break;
91 default:
92 fail("link " + src + " to " + dst);
93 }
94 }
95
96 private RefUpdate updateRef(final String name) throws IOException {
97 final RefUpdate ref = db.updateRef(name);
98 ref.setNewObjectId(db.resolve(Constants.HEAD));
99 return ref;
100 }
101
102 private void delete(final RefUpdate ref, final Result expected)
103 throws IOException {
104 delete(ref, expected, true, true);
105 }
106
107 private void delete(final RefUpdate ref, final Result expected,
108 final boolean exists, final boolean removed) throws IOException {
109 delete(db, ref, expected, exists, removed);
110 }
111
112 private void delete(Repository repo, final RefUpdate ref, final Result expected,
113 final boolean exists, final boolean removed) throws IOException {
114 assertEquals(exists, repo.getAllRefs().containsKey(ref.getName()));
115 assertEquals(expected, ref.delete());
116 assertEquals(!removed, repo.getAllRefs().containsKey(ref.getName()));
117 }
118
119 @Test
120 public void testNoCacheObjectIdSubclass() throws IOException {
121 final String newRef = "refs/heads/abc";
122 final RefUpdate ru = updateRef(newRef);
123 final SubclassedId newid = new SubclassedId(ru.getNewObjectId());
124 ru.setNewObjectId(newid);
125 Result update = ru.update();
126 assertEquals(Result.NEW, update);
127 final Ref r = db.getAllRefs().get(newRef);
128 assertNotNull(r);
129 assertEquals(newRef, r.getName());
130 assertNotNull(r.getObjectId());
131 assertNotSame(newid, r.getObjectId());
132 assertSame(ObjectId.class, r.getObjectId().getClass());
133 assertEquals(newid, r.getObjectId());
134 List<ReflogEntry> reverseEntries1 = db
135 .getReflogReader("refs/heads/abc").getReverseEntries();
136 ReflogEntry entry1 = reverseEntries1.get(0);
137 assertEquals(1, reverseEntries1.size());
138 assertEquals(ObjectId.zeroId(), entry1.getOldId());
139 assertEquals(r.getObjectId(), entry1.getNewId());
140 assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString());
141 assertEquals("", entry1.getComment());
142 List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD")
143 .getReverseEntries();
144 assertEquals(0, reverseEntries2.size());
145 }
146
147 @Test
148 public void testNewNamespaceConflictWithLoosePrefixNameExists()
149 throws IOException {
150 final String newRef = "refs/heads/z";
151 final RefUpdate ru = updateRef(newRef);
152 Result update = ru.update();
153 assertEquals(Result.NEW, update);
154
155 final String newRef2 = "refs/heads/z/a";
156 final RefUpdate ru2 = updateRef(newRef2);
157 Result update2 = ru2.update();
158 assertEquals(Result.LOCK_FAILURE, update2);
159 assertEquals(1, db.getReflogReader("refs/heads/z").getReverseEntries().size());
160 assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
161 }
162
163 @Test
164 public void testNewNamespaceConflictWithPackedPrefixNameExists()
165 throws IOException {
166 final String newRef = "refs/heads/master/x";
167 final RefUpdate ru = updateRef(newRef);
168 Result update = ru.update();
169 assertEquals(Result.LOCK_FAILURE, update);
170 assertNull(db.getReflogReader("refs/heads/master/x"));
171 assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
172 }
173
174 @Test
175 public void testNewNamespaceConflictWithLoosePrefixOfExisting()
176 throws IOException {
177 final String newRef = "refs/heads/z/a";
178 final RefUpdate ru = updateRef(newRef);
179 Result update = ru.update();
180 assertEquals(Result.NEW, update);
181
182 final String newRef2 = "refs/heads/z";
183 final RefUpdate ru2 = updateRef(newRef2);
184 Result update2 = ru2.update();
185 assertEquals(Result.LOCK_FAILURE, update2);
186 assertEquals(1, db.getReflogReader("refs/heads/z/a").getReverseEntries().size());
187 assertNull(db.getReflogReader("refs/heads/z"));
188 assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
189 }
190
191 @Test
192 public void testNewNamespaceConflictWithPackedPrefixOfExisting()
193 throws IOException {
194 final String newRef = "refs/heads/prefix";
195 final RefUpdate ru = updateRef(newRef);
196 Result update = ru.update();
197 assertEquals(Result.LOCK_FAILURE, update);
198 assertNull(db.getReflogReader("refs/heads/prefix"));
199 assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
200 }
201
202
203
204
205
206
207 @Test
208 public void testDeleteHEADreferencedRef() throws IOException {
209 ObjectId pid = db.resolve("refs/heads/master^");
210 RefUpdate updateRef = db.updateRef("refs/heads/master");
211 updateRef.setNewObjectId(pid);
212 updateRef.setForceUpdate(true);
213 Result update = updateRef.update();
214 assertEquals(Result.FORCED, update);
215
216 RefUpdate updateRef2 = db.updateRef("refs/heads/master");
217 Result delete = updateRef2.delete();
218 assertEquals(Result.REJECTED_CURRENT_BRANCH, delete);
219 assertEquals(pid, db.resolve("refs/heads/master"));
220 assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size());
221 assertEquals(0,db.getReflogReader("HEAD").getReverseEntries().size());
222 }
223
224 @Test
225 public void testLooseDelete() throws IOException {
226 final String newRef = "refs/heads/abc";
227 RefUpdate ref = updateRef(newRef);
228 ref.update();
229 ref = updateRef(newRef);
230 delete(ref, Result.NO_CHANGE);
231 assertNull(db.getReflogReader("refs/heads/abc"));
232 }
233
234 @Test
235 public void testDeleteHead() throws IOException {
236 final RefUpdate ref = updateRef(Constants.HEAD);
237 delete(ref, Result.REJECTED_CURRENT_BRANCH, true, false);
238 assertEquals(0, db.getReflogReader("refs/heads/master").getReverseEntries().size());
239 assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
240 }
241
242 @Test
243 public void testDeleteHeadInBareRepo() throws IOException {
244 Repository bareRepo = createBareRepository();
245 String master = "refs/heads/master";
246 Ref head = bareRepo.exactRef(Constants.HEAD);
247 assertNotNull(head);
248 assertTrue(head.isSymbolic());
249 assertEquals(master, head.getLeaf().getName());
250 assertNull(head.getObjectId());
251 assertNull(bareRepo.exactRef(master));
252
253 ObjectId blobId;
254 try (ObjectInserter ins = bareRepo.newObjectInserter()) {
255 blobId = ins.insert(Constants.OBJ_BLOB, "contents".getBytes(UTF_8));
256 ins.flush();
257 }
258
259
260 RefUpdate ref = bareRepo.updateRef(Constants.HEAD);
261 ref.setNewObjectId(blobId);
262 assertEquals(Result.NEW, ref.update());
263
264 head = bareRepo.exactRef(Constants.HEAD);
265 assertTrue(head.isSymbolic());
266 assertEquals(master, head.getLeaf().getName());
267 assertEquals(blobId, head.getLeaf().getObjectId());
268 assertEquals(blobId, bareRepo.exactRef(master).getObjectId());
269
270
271
272 ref = bareRepo.updateRef(Constants.HEAD);
273 ref.setExpectedOldObjectId(blobId);
274 ref.setForceUpdate(true);
275 delete(bareRepo, ref, Result.FORCED, true, true);
276
277 head = bareRepo.exactRef(Constants.HEAD);
278 assertNotNull(head);
279 assertTrue(head.isSymbolic());
280 assertEquals(master, head.getLeaf().getName());
281 assertNull(head.getObjectId());
282 assertNull(bareRepo.exactRef(master));
283 }
284
285 @Test
286 public void testDeleteSymref() throws IOException {
287 RefUpdate dst = updateRef("refs/heads/abc");
288 assertEquals(Result.NEW, dst.update());
289 ObjectId id = dst.getNewObjectId();
290
291 RefUpdate u = db.updateRef("refs/symref");
292 assertEquals(Result.NEW, u.link(dst.getName()));
293
294 Ref ref = db.exactRef(u.getName());
295 assertNotNull(ref);
296 assertTrue(ref.isSymbolic());
297 assertEquals(dst.getName(), ref.getLeaf().getName());
298 assertEquals(id, ref.getLeaf().getObjectId());
299
300 u = db.updateRef(u.getName());
301 u.setDetachingSymbolicRef();
302 u.setForceUpdate(true);
303 assertEquals(Result.FORCED, u.delete());
304
305 assertNull(db.exactRef(u.getName()));
306 ref = db.exactRef(dst.getName());
307 assertNotNull(ref);
308 assertFalse(ref.isSymbolic());
309 assertEquals(id, ref.getObjectId());
310 }
311
312
313
314
315
316
317
318 @Test
319 public void testDeleteLooseAndItsDirectory() throws IOException {
320 ObjectId pid = db.resolve("refs/heads/c^");
321 RefUpdate updateRef = db.updateRef("refs/heads/z/c");
322 updateRef.setNewObjectId(pid);
323 updateRef.setForceUpdate(true);
324 updateRef.setRefLogMessage("new test ref", false);
325 Result update = updateRef.update();
326 assertEquals(Result.NEW, update);
327 assertTrue(new File(db.getDirectory(), Constants.R_HEADS + "z")
328 .exists());
329 assertTrue(new File(db.getDirectory(), "logs/refs/heads/z").exists());
330
331
332 RefUpdate updateRef2 = db.updateRef("refs/heads/z/c");
333 updateRef2.setForceUpdate(true);
334 Result delete = updateRef2.delete();
335 assertEquals(Result.FORCED, delete);
336 assertNull(db.resolve("refs/heads/z/c"));
337 assertFalse(new File(db.getDirectory(), Constants.R_HEADS + "z")
338 .exists());
339 assertFalse(new File(db.getDirectory(), "logs/refs/heads/z").exists());
340 }
341
342 @Test
343 public void testDeleteNotFound() throws IOException {
344 final RefUpdate ref = updateRef("refs/heads/xyz");
345 delete(ref, Result.NEW, false, true);
346 }
347
348 @Test
349 public void testDeleteFastForward() throws IOException {
350 final RefUpdate ref = updateRef("refs/heads/a");
351 delete(ref, Result.FAST_FORWARD);
352 }
353
354 @Test
355 public void testDeleteForce() throws IOException {
356 final RefUpdate ref = db.updateRef("refs/heads/b");
357 ref.setNewObjectId(db.resolve("refs/heads/a"));
358 delete(ref, Result.REJECTED, true, false);
359 ref.setForceUpdate(true);
360 delete(ref, Result.FORCED);
361 }
362
363 @Test
364 public void testDeleteWithoutHead() throws IOException {
365
366 RefUpdate refUpdate = db.updateRef(Constants.HEAD, true);
367 refUpdate.setForceUpdate(true);
368 refUpdate.setNewObjectId(ObjectId.zeroId());
369 Result updateResult = refUpdate.update();
370 assertEquals(Result.FORCED, updateResult);
371 Result deleteHeadResult = db.updateRef(Constants.HEAD).delete();
372 assertEquals(Result.NO_CHANGE, deleteHeadResult);
373
374
375 db.updateRef(Constants.R_HEADS + "master").delete();
376 }
377
378 @Test
379 public void testRefKeySameAsName() {
380 Map<String, Ref> allRefs = db.getAllRefs();
381 for (Entry<String, Ref> e : allRefs.entrySet()) {
382 assertEquals(e.getKey(), e.getValue().getName());
383
384 }
385 }
386
387
388
389
390
391
392 @Test
393 public void testUpdateRefForward() throws IOException {
394 ObjectId ppid = db.resolve("refs/heads/master^");
395 ObjectId pid = db.resolve("refs/heads/master");
396
397 RefUpdate updateRef = db.updateRef("refs/heads/master");
398 updateRef.setNewObjectId(ppid);
399 updateRef.setForceUpdate(true);
400 Result update = updateRef.update();
401 assertEquals(Result.FORCED, update);
402 assertEquals(ppid, db.resolve("refs/heads/master"));
403
404
405 RefUpdate updateRef2 = db.updateRef("refs/heads/master");
406 updateRef2.setNewObjectId(pid);
407 Result update2 = updateRef2.update();
408 assertEquals(Result.FAST_FORWARD, update2);
409 assertEquals(pid, db.resolve("refs/heads/master"));
410 }
411
412
413
414
415
416
417 @Test
418 public void testUpdateRefDetached() throws Exception {
419 ObjectId pid = db.resolve("refs/heads/master");
420 ObjectId ppid = db.resolve("refs/heads/master^");
421 RefUpdate updateRef = db.updateRef("HEAD", true);
422 updateRef.setForceUpdate(true);
423 updateRef.setNewObjectId(ppid);
424 Result update = updateRef.update();
425 assertEquals(Result.FORCED, update);
426 assertEquals(ppid, db.resolve("HEAD"));
427 Ref ref = db.exactRef("HEAD");
428 assertEquals("HEAD", ref.getName());
429 assertTrue("is detached", !ref.isSymbolic());
430
431
432 assertEquals(pid, db.resolve("refs/heads/master"));
433 ReflogReader reflogReader = db.getReflogReader("HEAD");
434 ReflogEntry e = reflogReader.getReverseEntries().get(0);
435 assertEquals(pid, e.getOldId());
436 assertEquals(ppid, e.getNewId());
437 assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
438 assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
439 assertEquals(1250379778000L, e.getWho().getWhen().getTime());
440 }
441
442
443
444
445
446
447 @Test
448 public void testUpdateRefDetachedUnbornHead() throws Exception {
449 ObjectId ppid = db.resolve("refs/heads/master^");
450 writeSymref("HEAD", "refs/heads/unborn");
451 RefUpdate updateRef = db.updateRef("HEAD", true);
452 updateRef.setForceUpdate(true);
453 updateRef.setNewObjectId(ppid);
454 Result update = updateRef.update();
455 assertEquals(Result.NEW, update);
456 assertEquals(ppid, db.resolve("HEAD"));
457 Ref ref = db.exactRef("HEAD");
458 assertEquals("HEAD", ref.getName());
459 assertTrue("is detached", !ref.isSymbolic());
460
461
462 assertNull(db.resolve("refs/heads/unborn"));
463 ReflogReader reflogReader = db.getReflogReader("HEAD");
464 ReflogEntry e = reflogReader.getReverseEntries().get(0);
465 assertEquals(ObjectId.zeroId(), e.getOldId());
466 assertEquals(ppid, e.getNewId());
467 assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
468 assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
469 assertEquals(1250379778000L, e.getWho().getWhen().getTime());
470 }
471
472
473
474
475
476
477
478 @Test
479 public void testDeleteLoosePacked() throws IOException {
480 ObjectId pid = db.resolve("refs/heads/c^");
481 RefUpdate updateRef = db.updateRef("refs/heads/c");
482 updateRef.setNewObjectId(pid);
483 updateRef.setForceUpdate(true);
484 Result update = updateRef.update();
485 assertEquals(Result.FORCED, update);
486
487
488 RefUpdate updateRef2 = db.updateRef("refs/heads/c");
489 updateRef2.setForceUpdate(true);
490 Result delete = updateRef2.delete();
491 assertEquals(Result.FORCED, delete);
492 assertNull(db.resolve("refs/heads/c"));
493 }
494
495
496
497
498
499
500 @Test
501 public void testUpdateRefNoChange() throws IOException {
502 ObjectId pid = db.resolve("refs/heads/master");
503 RefUpdate updateRef = db.updateRef("refs/heads/master");
504 updateRef.setNewObjectId(pid);
505 Result update = updateRef.update();
506 assertEquals(Result.NO_CHANGE, update);
507 assertEquals(pid, db.resolve("refs/heads/master"));
508 }
509
510
511
512
513
514
515
516
517
518
519
520 @Test
521 public void testRefsCacheAfterUpdate() throws Exception {
522
523 Map<String, Ref> allRefs = db.getAllRefs();
524 ObjectId oldValue = db.resolve("HEAD");
525 ObjectId newValue = db.resolve("HEAD^");
526
527 RefUpdate updateRef = db.updateRef(Constants.HEAD);
528 updateRef.setForceUpdate(true);
529 updateRef.setNewObjectId(newValue);
530 Result update = updateRef.update();
531 assertEquals(Result.FORCED, update);
532
533
534 updateRef = db.updateRef(Constants.HEAD);
535 updateRef.setNewObjectId(oldValue);
536 update = updateRef.update();
537 assertEquals(Result.FAST_FORWARD, update);
538
539 allRefs = db.getAllRefs();
540 Ref master = allRefs.get("refs/heads/master");
541 Ref head = allRefs.get("HEAD");
542 assertEquals("refs/heads/master", master.getName());
543 assertEquals("HEAD", head.getName());
544 assertTrue("is symbolic reference", head.isSymbolic());
545 assertSame(master, head.getTarget());
546 }
547
548
549
550
551
552
553
554
555
556
557 @Test
558 public void testRefsCacheAfterUpdateLooseOnly() throws Exception {
559
560 Map<String, Ref> allRefs = db.getAllRefs();
561 ObjectId oldValue = db.resolve("HEAD");
562 writeSymref(Constants.HEAD, "refs/heads/newref");
563 RefUpdate updateRef = db.updateRef(Constants.HEAD);
564 updateRef.setForceUpdate(true);
565 updateRef.setNewObjectId(oldValue);
566 Result update = updateRef.update();
567 assertEquals(Result.NEW, update);
568
569 allRefs = db.getAllRefs();
570 Ref head = allRefs.get("HEAD");
571 Ref newref = allRefs.get("refs/heads/newref");
572 assertEquals("refs/heads/newref", newref.getName());
573 assertEquals("HEAD", head.getName());
574 assertTrue("is symbolic reference", head.isSymbolic());
575 assertSame(newref, head.getTarget());
576 }
577
578
579
580
581
582
583 @Test
584 public void testUpdateRefLockFailureWrongOldValue() throws IOException {
585 ObjectId pid = db.resolve("refs/heads/master");
586 RefUpdate updateRef = db.updateRef("refs/heads/master");
587 updateRef.setNewObjectId(pid);
588 updateRef.setExpectedOldObjectId(db.resolve("refs/heads/master^"));
589 Result update = updateRef.update();
590 assertEquals(Result.LOCK_FAILURE, update);
591 assertEquals(pid, db.resolve("refs/heads/master"));
592 }
593
594
595
596
597
598
599 @Test
600 public void testUpdateRefForwardWithCheck1() throws IOException {
601 ObjectId ppid = db.resolve("refs/heads/master^");
602 ObjectId pid = db.resolve("refs/heads/master");
603
604 RefUpdate updateRef = db.updateRef("refs/heads/master");
605 updateRef.setNewObjectId(ppid);
606 updateRef.setForceUpdate(true);
607 Result update = updateRef.update();
608 assertEquals(Result.FORCED, update);
609 assertEquals(ppid, db.resolve("refs/heads/master"));
610
611
612 RefUpdate updateRef2 = db.updateRef("refs/heads/master");
613 updateRef2.setExpectedOldObjectId(ppid);
614 updateRef2.setNewObjectId(pid);
615 Result update2 = updateRef2.update();
616 assertEquals(Result.FAST_FORWARD, update2);
617 assertEquals(pid, db.resolve("refs/heads/master"));
618 }
619
620
621
622
623
624
625 @Test
626 public void testUpdateRefForwardWithCheck2() throws IOException {
627 ObjectId ppid = db.resolve("refs/heads/master^");
628 ObjectId pid = db.resolve("refs/heads/master");
629
630 RefUpdate updateRef = db.updateRef("refs/heads/master");
631 updateRef.setNewObjectId(ppid);
632 updateRef.setForceUpdate(true);
633 Result update = updateRef.update();
634 assertEquals(Result.FORCED, update);
635 assertEquals(ppid, db.resolve("refs/heads/master"));
636
637
638 try (RevWalk rw = new RevWalk(db)) {
639 RevCommit old = rw.parseCommit(ppid);
640 RefUpdate updateRef2 = db.updateRef("refs/heads/master");
641 updateRef2.setExpectedOldObjectId(old);
642 updateRef2.setNewObjectId(pid);
643 Result update2 = updateRef2.update();
644 assertEquals(Result.FAST_FORWARD, update2);
645 assertEquals(pid, db.resolve("refs/heads/master"));
646 }
647 }
648
649
650
651
652
653
654 @Test
655 public void testUpdateRefLockFailureLocked() throws IOException {
656 ObjectId opid = db.resolve("refs/heads/master");
657 ObjectId pid = db.resolve("refs/heads/master^");
658 RefUpdate updateRef = db.updateRef("refs/heads/master");
659 updateRef.setNewObjectId(pid);
660 LockFile lockFile1 = new LockFile(new File(db.getDirectory(),
661 "refs/heads/master"));
662 try {
663 assertTrue(lockFile1.lock());
664 Result update = updateRef.update();
665 assertEquals(Result.LOCK_FAILURE, update);
666 assertEquals(opid, db.resolve("refs/heads/master"));
667 LockFile lockFile2 = new LockFile(new File(db.getDirectory(),"refs/heads/master"));
668 assertFalse(lockFile2.lock());
669 } finally {
670 lockFile1.unlock();
671 }
672 }
673
674
675
676
677
678
679 @Test
680 public void testDeleteLoosePackedRejected() throws IOException {
681 ObjectId pid = db.resolve("refs/heads/c^");
682 ObjectId oldpid = db.resolve("refs/heads/c");
683 RefUpdate updateRef = db.updateRef("refs/heads/c");
684 updateRef.setNewObjectId(pid);
685 Result update = updateRef.update();
686 assertEquals(Result.REJECTED, update);
687 assertEquals(oldpid, db.resolve("refs/heads/c"));
688 }
689
690 @Test
691 public void testRenameBranchNoPreviousLog() throws IOException {
692 assertFalse("precondition, no log on old branchg", new File(db
693 .getDirectory(), "logs/refs/heads/b").exists());
694 ObjectId rb = db.resolve("refs/heads/b");
695 ObjectId oldHead = db.resolve(Constants.HEAD);
696 assertFalse(rb.equals(oldHead));
697 RefRename renameRef = db.renameRef("refs/heads/b",
698 "refs/heads/new/name");
699 Result result = renameRef.rename();
700 assertEquals(Result.RENAMED, result);
701 assertEquals(rb, db.resolve("refs/heads/new/name"));
702 assertNull(db.resolve("refs/heads/b"));
703 assertEquals(1, db.getReflogReader("new/name").getReverseEntries().size());
704 assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name")
705 .getLastEntry().getComment());
706 assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
707 assertEquals(oldHead, db.resolve(Constants.HEAD));
708 }
709
710 @Test
711 public void testRenameBranchHasPreviousLog() throws IOException {
712 ObjectId rb = db.resolve("refs/heads/b");
713 ObjectId oldHead = db.resolve(Constants.HEAD);
714 assertFalse("precondition for this test, branch b != HEAD", rb
715 .equals(oldHead));
716 writeReflog(db, rb, "Just a message", "refs/heads/b");
717 assertTrue("log on old branch", new File(db.getDirectory(),
718 "logs/refs/heads/b").exists());
719 RefRename renameRef = db.renameRef("refs/heads/b",
720 "refs/heads/new/name");
721 Result result = renameRef.rename();
722 assertEquals(Result.RENAMED, result);
723 assertEquals(rb, db.resolve("refs/heads/new/name"));
724 assertNull(db.resolve("refs/heads/b"));
725 assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size());
726 assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name")
727 .getLastEntry().getComment());
728 assertEquals("Just a message", db.getReflogReader("new/name")
729 .getReverseEntries().get(1).getComment());
730 assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
731 assertEquals(oldHead, db.resolve(Constants.HEAD));
732 }
733
734 @Test
735 public void testRenameCurrentBranch() throws IOException {
736 ObjectId rb = db.resolve("refs/heads/b");
737 writeSymref(Constants.HEAD, "refs/heads/b");
738 ObjectId oldHead = db.resolve(Constants.HEAD);
739 assertEquals("internal test condition, b == HEAD", oldHead, rb);
740 writeReflog(db, rb, "Just a message", "refs/heads/b");
741 assertTrue("log on old branch", new File(db.getDirectory(),
742 "logs/refs/heads/b").exists());
743 RefRename renameRef = db.renameRef("refs/heads/b",
744 "refs/heads/new/name");
745 Result result = renameRef.rename();
746 assertEquals(Result.RENAMED, result);
747 assertEquals(rb, db.resolve("refs/heads/new/name"));
748 assertNull(db.resolve("refs/heads/b"));
749 assertEquals("Branch: renamed b to new/name", db.getReflogReader(
750 "new/name").getLastEntry().getComment());
751 assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
752 assertEquals(rb, db.resolve(Constants.HEAD));
753 assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size());
754 assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name").getReverseEntries().get(0).getComment());
755 assertEquals("Just a message", db.getReflogReader("new/name").getReverseEntries().get(1).getComment());
756 }
757
758 @Test
759 public void testRenameBranchAlsoInPack() throws IOException {
760 ObjectId rb = db.resolve("refs/heads/b");
761 ObjectId rb2 = db.resolve("refs/heads/b~1");
762 assertEquals(Ref.Storage.PACKED, db.exactRef("refs/heads/b").getStorage());
763 RefUpdate updateRef = db.updateRef("refs/heads/b");
764 updateRef.setNewObjectId(rb2);
765 updateRef.setForceUpdate(true);
766 Result update = updateRef.update();
767 assertEquals("internal check new ref is loose", Result.FORCED, update);
768 assertEquals(Ref.Storage.LOOSE, db.exactRef("refs/heads/b").getStorage());
769 writeReflog(db, rb, "Just a message", "refs/heads/b");
770 assertTrue("log on old branch", new File(db.getDirectory(),
771 "logs/refs/heads/b").exists());
772 RefRename renameRef = db.renameRef("refs/heads/b",
773 "refs/heads/new/name");
774 Result result = renameRef.rename();
775 assertEquals(Result.RENAMED, result);
776 assertEquals(rb2, db.resolve("refs/heads/new/name"));
777 assertNull(db.resolve("refs/heads/b"));
778 assertEquals("Branch: renamed b to new/name", db.getReflogReader(
779 "new/name").getLastEntry().getComment());
780 assertEquals(3, db.getReflogReader("refs/heads/new/name").getReverseEntries().size());
781 assertEquals("Branch: renamed b to new/name", db.getReflogReader("refs/heads/new/name").getReverseEntries().get(0).getComment());
782 assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
783
784 assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
785
786
787
788 try (Repository ndb = new FileRepository(db.getDirectory())) {
789 assertEquals(rb2, ndb.resolve("refs/heads/new/name"));
790 assertNull(ndb.resolve("refs/heads/b"));
791 }
792 }
793
794 public void tryRenameWhenLocked(String toLock, String fromName,
795 String toName, String headPointsTo) throws IOException {
796
797 writeSymref(Constants.HEAD, headPointsTo);
798 ObjectId oldfromId = db.resolve(fromName);
799 ObjectId oldHeadId = db.resolve(Constants.HEAD);
800 writeReflog(db, oldfromId, "Just a message", fromName);
801 List<ReflogEntry> oldFromLog = db
802 .getReflogReader(fromName).getReverseEntries();
803 List<ReflogEntry> oldHeadLog = oldHeadId != null ? db
804 .getReflogReader(Constants.HEAD).getReverseEntries() : null;
805
806 assertTrue("internal check, we have a log", new File(db.getDirectory(),
807 "logs/" + fromName).exists());
808
809
810 LockFile lockFile = new LockFile(new File(db.getDirectory(), toLock));
811 try {
812 assertTrue(lockFile.lock());
813
814
815 RefRename renameRef = db.renameRef(fromName, toName);
816 Result result = renameRef.rename();
817 assertEquals(Result.LOCK_FAILURE, result);
818
819
820 assertExists(false, toName);
821 if (!toLock.equals(toName))
822 assertExists(false, toName + ".lock");
823 assertExists(true, toLock + ".lock");
824 if (!toLock.equals(fromName))
825 assertExists(false, "logs/" + fromName + ".lock");
826 assertExists(false, "logs/" + toName + ".lock");
827 assertEquals(oldHeadId, db.resolve(Constants.HEAD));
828 assertEquals(oldfromId, db.resolve(fromName));
829 assertNull(db.resolve(toName));
830 assertEquals(oldFromLog.toString(), db.getReflogReader(fromName)
831 .getReverseEntries().toString());
832 if (oldHeadId != null && oldHeadLog != null)
833 assertEquals(oldHeadLog.toString(), db.getReflogReader(
834 Constants.HEAD).getReverseEntries().toString());
835 } finally {
836 lockFile.unlock();
837 }
838 }
839
840 private void assertExists(boolean positive, String toName) {
841 assertEquals(toName + (positive ? " " : " does not ") + "exist",
842 positive, new File(db.getDirectory(), toName).exists());
843 }
844
845 @Test
846 public void testRenameBranchCannotLockAFileHEADisFromLockHEAD()
847 throws IOException {
848 tryRenameWhenLocked("HEAD", "refs/heads/b", "refs/heads/new/name",
849 "refs/heads/b");
850 }
851
852 @Test
853 public void testRenameBranchCannotLockAFileHEADisFromLockFrom()
854 throws IOException {
855 tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
856 "refs/heads/new/name", "refs/heads/b");
857 }
858
859 @Test
860 public void testRenameBranchCannotLockAFileHEADisFromLockTo()
861 throws IOException {
862 tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
863 "refs/heads/new/name", "refs/heads/b");
864 }
865
866 @Test
867 public void testRenameBranchCannotLockAFileHEADisToLockFrom()
868 throws IOException {
869 tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
870 "refs/heads/new/name", "refs/heads/new/name");
871 }
872
873 @Test
874 public void testRenameBranchCannotLockAFileHEADisToLockTo()
875 throws IOException {
876 tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
877 "refs/heads/new/name", "refs/heads/new/name");
878 }
879
880 @Test
881 public void testRenameBranchCannotLockAFileHEADisOtherLockFrom()
882 throws IOException {
883 tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
884 "refs/heads/new/name", "refs/heads/a");
885 }
886
887 @Test
888 public void testRenameBranchCannotLockAFileHEADisOtherLockTo()
889 throws IOException {
890 tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
891 "refs/heads/new/name", "refs/heads/a");
892 }
893
894 @Test
895 public void testRenameRefNameColission1avoided() throws IOException {
896
897 ObjectId rb = db.resolve("refs/heads/b");
898 writeSymref(Constants.HEAD, "refs/heads/a");
899 RefUpdate updateRef = db.updateRef("refs/heads/a");
900 updateRef.setNewObjectId(rb);
901 updateRef.setRefLogMessage("Setup", false);
902 assertEquals(Result.FAST_FORWARD, updateRef.update());
903 ObjectId oldHead = db.resolve(Constants.HEAD);
904 assertEquals(oldHead, rb);
905 writeReflog(db, rb, "Just a message", "refs/heads/a");
906 assertTrue("internal check, we have a log", new File(db.getDirectory(),
907 "logs/refs/heads/a").exists());
908
909
910 RefRename renameRef = db.renameRef("refs/heads/a", "refs/heads/a/b");
911 Result result = renameRef.rename();
912 assertEquals(Result.RENAMED, result);
913 assertNull(db.resolve("refs/heads/a"));
914 assertEquals(rb, db.resolve("refs/heads/a/b"));
915 assertEquals(3, db.getReflogReader("a/b").getReverseEntries().size());
916 assertEquals("Branch: renamed a to a/b", db.getReflogReader("a/b")
917 .getReverseEntries().get(0).getComment());
918 assertEquals("Just a message", db.getReflogReader("a/b")
919 .getReverseEntries().get(1).getComment());
920 assertEquals("Setup", db.getReflogReader("a/b").getReverseEntries()
921 .get(2).getComment());
922
923 assertEquals("Branch: renamed a to a/b", db.getReflogReader("HEAD")
924 .getReverseEntries().get(0).getComment());
925 }
926
927 @Test
928 public void testRenameRefNameColission2avoided() throws IOException {
929
930 ObjectId rb = db.resolve("refs/heads/b");
931 writeSymref(Constants.HEAD, "refs/heads/prefix/a");
932 RefUpdate updateRef = db.updateRef("refs/heads/prefix/a");
933 updateRef.setNewObjectId(rb);
934 updateRef.setRefLogMessage("Setup", false);
935 updateRef.setForceUpdate(true);
936 assertEquals(Result.FORCED, updateRef.update());
937 ObjectId oldHead = db.resolve(Constants.HEAD);
938 assertEquals(oldHead, rb);
939 writeReflog(db, rb, "Just a message", "refs/heads/prefix/a");
940 assertTrue("internal check, we have a log", new File(db.getDirectory(),
941 "logs/refs/heads/prefix/a").exists());
942
943
944 RefRename renameRef = db.renameRef("refs/heads/prefix/a",
945 "refs/heads/prefix");
946 Result result = renameRef.rename();
947 assertEquals(Result.RENAMED, result);
948
949 assertNull(db.resolve("refs/heads/prefix/a"));
950 assertEquals(rb, db.resolve("refs/heads/prefix"));
951 assertEquals(3, db.getReflogReader("prefix").getReverseEntries().size());
952 assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader(
953 "prefix").getReverseEntries().get(0).getComment());
954 assertEquals("Just a message", db.getReflogReader("prefix")
955 .getReverseEntries().get(1).getComment());
956 assertEquals("Setup", db.getReflogReader("prefix").getReverseEntries()
957 .get(2).getComment());
958 assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader(
959 "HEAD").getReverseEntries().get(0).getComment());
960 }
961
962 @Test
963 public void testCreateMissingObject() throws IOException {
964 String name = "refs/heads/abc";
965 ObjectId bad =
966 ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
967 RefUpdate ru = db.updateRef(name);
968 ru.setNewObjectId(bad);
969 Result update = ru.update();
970 assertEquals(Result.REJECTED_MISSING_OBJECT, update);
971
972 Ref ref = db.exactRef(name);
973 assertNull(ref);
974 }
975
976 @Test
977 public void testUpdateMissingObject() throws IOException {
978 String name = "refs/heads/abc";
979 RefUpdate ru = updateRef(name);
980 Result update = ru.update();
981 assertEquals(Result.NEW, update);
982 ObjectId oldId = ru.getNewObjectId();
983
984 ObjectId bad =
985 ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
986 ru = db.updateRef(name);
987 ru.setNewObjectId(bad);
988 update = ru.update();
989 assertEquals(Result.REJECTED_MISSING_OBJECT, update);
990
991 Ref ref = db.exactRef(name);
992 assertNotNull(ref);
993 assertEquals(oldId, ref.getObjectId());
994 }
995
996 @Test
997 public void testForceUpdateMissingObject() throws IOException {
998 String name = "refs/heads/abc";
999 RefUpdate ru = updateRef(name);
1000 Result update = ru.update();
1001 assertEquals(Result.NEW, update);
1002 ObjectId oldId = ru.getNewObjectId();
1003
1004 ObjectId bad =
1005 ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
1006 ru = db.updateRef(name);
1007 ru.setNewObjectId(bad);
1008 update = ru.forceUpdate();
1009 assertEquals(Result.REJECTED_MISSING_OBJECT, update);
1010
1011 Ref ref = db.exactRef(name);
1012 assertNotNull(ref);
1013 assertEquals(oldId, ref.getObjectId());
1014 }
1015
1016 private static void writeReflog(Repository db, ObjectId newId, String msg,
1017 String refName) throws IOException {
1018 RefDirectory refs = (RefDirectory) db.getRefDatabase();
1019 RefDirectoryUpdate update = refs.newUpdate(refName, true);
1020 update.setNewObjectId(newId);
1021 refs.log(false, update, msg, true);
1022 }
1023
1024 private static class SubclassedId extends ObjectId {
1025 SubclassedId(AnyObjectId src) {
1026 super(src);
1027 }
1028 }
1029 }