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