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 package org.eclipse.jgit.internal.storage.file;
45
46 import static org.eclipse.jgit.lib.Constants.HEAD;
47 import static org.eclipse.jgit.lib.Constants.R_HEADS;
48 import static org.eclipse.jgit.lib.Constants.R_TAGS;
49 import static org.eclipse.jgit.lib.Ref.Storage.LOOSE;
50 import static org.eclipse.jgit.lib.Ref.Storage.NEW;
51 import static org.junit.Assert.assertEquals;
52 import static org.junit.Assert.assertFalse;
53 import static org.junit.Assert.assertNotNull;
54 import static org.junit.Assert.assertNotSame;
55 import static org.junit.Assert.assertNull;
56 import static org.junit.Assert.assertSame;
57 import static org.junit.Assert.assertTrue;
58 import static org.junit.Assert.fail;
59
60 import java.io.File;
61 import java.io.IOException;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.List;
65 import java.util.Map;
66 import java.util.concurrent.atomic.AtomicInteger;
67 import java.util.concurrent.atomic.AtomicReference;
68
69 import org.eclipse.jgit.events.ListenerHandle;
70 import org.eclipse.jgit.events.RefsChangedEvent;
71 import org.eclipse.jgit.events.RefsChangedListener;
72 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
73 import org.eclipse.jgit.junit.TestRepository;
74 import org.eclipse.jgit.lib.AnyObjectId;
75 import org.eclipse.jgit.lib.BatchRefUpdate;
76 import org.eclipse.jgit.lib.ProgressMonitor;
77 import org.eclipse.jgit.lib.NullProgressMonitor;
78 import org.eclipse.jgit.lib.Ref;
79 import org.eclipse.jgit.lib.Ref.Storage;
80 import org.eclipse.jgit.lib.RefDatabase;
81 import org.eclipse.jgit.lib.Repository;
82 import org.eclipse.jgit.revwalk.RevCommit;
83 import org.eclipse.jgit.revwalk.RevTag;
84 import org.eclipse.jgit.revwalk.RevWalk;
85 import org.eclipse.jgit.transport.ReceiveCommand;
86 import org.eclipse.jgit.transport.ReceiveCommand.Type;
87 import org.junit.Before;
88 import org.junit.Test;
89
90 public class RefDirectoryTest extends LocalDiskRepositoryTestCase {
91 private Repository diskRepo;
92
93 private TestRepository<Repository> repo;
94
95 private RefDirectory refdir;
96
97 private RevCommit A;
98
99 private RevCommit B;
100
101 private RevTag v1_0;
102
103 @Before
104 public void setUp() throws Exception {
105 super.setUp();
106
107 diskRepo = createBareRepository();
108 refdir = (RefDirectory) diskRepo.getRefDatabase();
109
110 repo = new TestRepository<Repository>(diskRepo);
111 A = repo.commit().create();
112 B = repo.commit(repo.getRevWalk().parseCommit(A));
113 v1_0 = repo.tag("v1_0", B);
114 repo.getRevWalk().parseBody(v1_0);
115 }
116
117 @Test
118 public void testCreate() throws IOException {
119
120 File d = diskRepo.getDirectory();
121 assertSame(diskRepo, refdir.getRepository());
122
123 assertTrue(new File(d, "refs").isDirectory());
124 assertTrue(new File(d, "logs").isDirectory());
125 assertTrue(new File(d, "logs/refs").isDirectory());
126 assertFalse(new File(d, "packed-refs").exists());
127
128 assertTrue(new File(d, "refs/heads").isDirectory());
129 assertTrue(new File(d, "refs/tags").isDirectory());
130 assertEquals(2, new File(d, "refs").list().length);
131 assertEquals(0, new File(d, "refs/heads").list().length);
132 assertEquals(0, new File(d, "refs/tags").list().length);
133
134 assertTrue(new File(d, "logs/refs/heads").isDirectory());
135 assertFalse(new File(d, "logs/HEAD").exists());
136 assertEquals(0, new File(d, "logs/refs/heads").list().length);
137
138 assertEquals("ref: refs/heads/master\n", read(new File(d, HEAD)));
139 }
140
141 @Test
142 public void testGetRefs_EmptyDatabase() throws IOException {
143 Map<String, Ref> all;
144
145 all = refdir.getRefs(RefDatabase.ALL);
146 assertTrue("no references", all.isEmpty());
147
148 all = refdir.getRefs(R_HEADS);
149 assertTrue("no references", all.isEmpty());
150
151 all = refdir.getRefs(R_TAGS);
152 assertTrue("no references", all.isEmpty());
153 }
154
155 @Test
156 public void testGetRefs_HeadOnOneBranch() throws IOException {
157 Map<String, Ref> all;
158 Ref head, master;
159
160 writeLooseRef("refs/heads/master", A);
161
162 all = refdir.getRefs(RefDatabase.ALL);
163 assertEquals(2, all.size());
164 assertTrue("has HEAD", all.containsKey(HEAD));
165 assertTrue("has master", all.containsKey("refs/heads/master"));
166
167 head = all.get(HEAD);
168 master = all.get("refs/heads/master");
169
170 assertEquals(HEAD, head.getName());
171 assertTrue(head.isSymbolic());
172 assertSame(LOOSE, head.getStorage());
173 assertSame("uses same ref as target", master, head.getTarget());
174
175 assertEquals("refs/heads/master", master.getName());
176 assertFalse(master.isSymbolic());
177 assertSame(LOOSE, master.getStorage());
178 assertEquals(A, master.getObjectId());
179 }
180
181 @Test
182 public void testGetRefs_DeatchedHead1() throws IOException {
183 Map<String, Ref> all;
184 Ref head;
185
186 writeLooseRef(HEAD, A);
187
188 all = refdir.getRefs(RefDatabase.ALL);
189 assertEquals(1, all.size());
190 assertTrue("has HEAD", all.containsKey(HEAD));
191
192 head = all.get(HEAD);
193
194 assertEquals(HEAD, head.getName());
195 assertFalse(head.isSymbolic());
196 assertSame(LOOSE, head.getStorage());
197 assertEquals(A, head.getObjectId());
198 }
199
200 @Test
201 public void testGetRefs_DeatchedHead2() throws IOException {
202 Map<String, Ref> all;
203 Ref head, master;
204
205 writeLooseRef(HEAD, A);
206 writeLooseRef("refs/heads/master", B);
207
208 all = refdir.getRefs(RefDatabase.ALL);
209 assertEquals(2, all.size());
210
211 head = all.get(HEAD);
212 master = all.get("refs/heads/master");
213
214 assertEquals(HEAD, head.getName());
215 assertFalse(head.isSymbolic());
216 assertSame(LOOSE, head.getStorage());
217 assertEquals(A, head.getObjectId());
218
219 assertEquals("refs/heads/master", master.getName());
220 assertFalse(master.isSymbolic());
221 assertSame(LOOSE, master.getStorage());
222 assertEquals(B, master.getObjectId());
223 }
224
225 @Test
226 public void testGetRefs_DeeplyNestedBranch() throws IOException {
227 String name = "refs/heads/a/b/c/d/e/f/g/h/i/j/k";
228 Map<String, Ref> all;
229 Ref r;
230
231 writeLooseRef(name, A);
232
233 all = refdir.getRefs(RefDatabase.ALL);
234 assertEquals(1, all.size());
235
236 r = all.get(name);
237 assertEquals(name, r.getName());
238 assertFalse(r.isSymbolic());
239 assertSame(LOOSE, r.getStorage());
240 assertEquals(A, r.getObjectId());
241 }
242
243 @Test
244 public void testGetRefs_HeadBranchNotBorn() throws IOException {
245 Map<String, Ref> all;
246 Ref a, b;
247
248 writeLooseRef("refs/heads/A", A);
249 writeLooseRef("refs/heads/B", B);
250
251 all = refdir.getRefs(RefDatabase.ALL);
252 assertEquals(2, all.size());
253 assertFalse("no HEAD", all.containsKey(HEAD));
254
255 a = all.get("refs/heads/A");
256 b = all.get("refs/heads/B");
257
258 assertEquals(A, a.getObjectId());
259 assertEquals(B, b.getObjectId());
260
261 assertEquals("refs/heads/A", a.getName());
262 assertEquals("refs/heads/B", b.getName());
263 }
264
265 @Test
266 public void testGetRefs_LooseOverridesPacked() throws IOException {
267 Map<String, Ref> heads;
268 Ref a;
269
270 writeLooseRef("refs/heads/master", B);
271 writePackedRef("refs/heads/master", A);
272
273 heads = refdir.getRefs(R_HEADS);
274 assertEquals(1, heads.size());
275
276 a = heads.get("master");
277 assertEquals("refs/heads/master", a.getName());
278 assertEquals(B, a.getObjectId());
279 }
280
281 @Test
282 public void testGetRefs_IgnoresGarbageRef1() throws IOException {
283 Map<String, Ref> heads;
284 Ref a;
285
286 writeLooseRef("refs/heads/A", A);
287 write(new File(diskRepo.getDirectory(), "refs/heads/bad"), "FAIL\n");
288
289 heads = refdir.getRefs(RefDatabase.ALL);
290 assertEquals(1, heads.size());
291
292 a = heads.get("refs/heads/A");
293 assertEquals("refs/heads/A", a.getName());
294 assertEquals(A, a.getObjectId());
295 }
296
297 @Test
298 public void testGetRefs_IgnoresGarbageRef2() throws IOException {
299 Map<String, Ref> heads;
300 Ref a;
301
302 writeLooseRef("refs/heads/A", A);
303 write(new File(diskRepo.getDirectory(), "refs/heads/bad"), "");
304
305 heads = refdir.getRefs(RefDatabase.ALL);
306 assertEquals(1, heads.size());
307
308 a = heads.get("refs/heads/A");
309 assertEquals("refs/heads/A", a.getName());
310 assertEquals(A, a.getObjectId());
311 }
312
313 @Test
314 public void testGetRefs_IgnoresGarbageRef3() throws IOException {
315 Map<String, Ref> heads;
316 Ref a;
317
318 writeLooseRef("refs/heads/A", A);
319 write(new File(diskRepo.getDirectory(), "refs/heads/bad"), "\n");
320
321 heads = refdir.getRefs(RefDatabase.ALL);
322 assertEquals(1, heads.size());
323
324 a = heads.get("refs/heads/A");
325 assertEquals("refs/heads/A", a.getName());
326 assertEquals(A, a.getObjectId());
327 }
328
329 @Test
330 public void testGetRefs_IgnoresGarbageRef4() throws IOException {
331 Map<String, Ref> heads;
332 Ref a, b, c;
333
334 writeLooseRef("refs/heads/A", A);
335 writeLooseRef("refs/heads/B", B);
336 writeLooseRef("refs/heads/C", A);
337 heads = refdir.getRefs(RefDatabase.ALL);
338 assertEquals(3, heads.size());
339 assertTrue(heads.containsKey("refs/heads/A"));
340 assertTrue(heads.containsKey("refs/heads/B"));
341 assertTrue(heads.containsKey("refs/heads/C"));
342
343 writeLooseRef("refs/heads/B", "FAIL\n");
344
345 heads = refdir.getRefs(RefDatabase.ALL);
346 assertEquals(2, heads.size());
347
348 a = heads.get("refs/heads/A");
349 b = heads.get("refs/heads/B");
350 c = heads.get("refs/heads/C");
351
352 assertEquals("refs/heads/A", a.getName());
353 assertEquals(A, a.getObjectId());
354
355 assertNull("no refs/heads/B", b);
356
357 assertEquals("refs/heads/C", c.getName());
358 assertEquals(A, c.getObjectId());
359 }
360
361 @Test
362 public void testGetRefs_InvalidName() throws IOException {
363 writeLooseRef("refs/heads/A", A);
364
365 assertTrue("empty refs/heads", refdir.getRefs("refs/heads").isEmpty());
366 assertTrue("empty objects", refdir.getRefs("objects").isEmpty());
367 assertTrue("empty objects/", refdir.getRefs("objects/").isEmpty());
368 }
369
370 @Test
371 public void testReadNotExistingBranchConfig() throws IOException {
372 assertNull("find branch config", refdir.getRef("config"));
373 assertNull("find branch config", refdir.getRef("refs/heads/config"));
374 }
375
376 @Test
377 public void testReadBranchConfig() throws IOException {
378 writeLooseRef("refs/heads/config", A);
379
380 assertNotNull("find branch config", refdir.getRef("config"));
381 }
382
383 @Test
384 public void testGetRefs_HeadsOnly_AllLoose() throws IOException {
385 Map<String, Ref> heads;
386 Ref a, b;
387
388 writeLooseRef("refs/heads/A", A);
389 writeLooseRef("refs/heads/B", B);
390 writeLooseRef("refs/tags/v1.0", v1_0);
391
392 heads = refdir.getRefs(R_HEADS);
393 assertEquals(2, heads.size());
394
395 a = heads.get("A");
396 b = heads.get("B");
397
398 assertEquals("refs/heads/A", a.getName());
399 assertEquals("refs/heads/B", b.getName());
400
401 assertEquals(A, a.getObjectId());
402 assertEquals(B, b.getObjectId());
403 }
404
405 @Test
406 public void testGetRefs_HeadsOnly_AllPacked1() throws IOException {
407 Map<String, Ref> heads;
408 Ref a;
409
410 deleteLooseRef(HEAD);
411 writePackedRef("refs/heads/A", A);
412
413 heads = refdir.getRefs(R_HEADS);
414 assertEquals(1, heads.size());
415
416 a = heads.get("A");
417
418 assertEquals("refs/heads/A", a.getName());
419 assertEquals(A, a.getObjectId());
420 }
421
422 @Test
423 public void testGetRefs_HeadsOnly_SymrefToPacked() throws IOException {
424 Map<String, Ref> heads;
425 Ref master, other;
426
427 writeLooseRef("refs/heads/other", "ref: refs/heads/master\n");
428 writePackedRef("refs/heads/master", A);
429
430 heads = refdir.getRefs(R_HEADS);
431 assertEquals(2, heads.size());
432
433 master = heads.get("master");
434 other = heads.get("other");
435
436 assertEquals("refs/heads/master", master.getName());
437 assertEquals(A, master.getObjectId());
438
439 assertEquals("refs/heads/other", other.getName());
440 assertEquals(A, other.getObjectId());
441 assertSame(master, other.getTarget());
442 }
443
444 @Test
445 public void testGetRefs_HeadsOnly_Mixed() throws IOException {
446 Map<String, Ref> heads;
447 Ref a, b;
448
449 writeLooseRef("refs/heads/A", A);
450 writeLooseRef("refs/heads/B", B);
451 writePackedRef("refs/tags/v1.0", v1_0);
452
453 heads = refdir.getRefs(R_HEADS);
454 assertEquals(2, heads.size());
455
456 a = heads.get("A");
457 b = heads.get("B");
458
459 assertEquals("refs/heads/A", a.getName());
460 assertEquals("refs/heads/B", b.getName());
461
462 assertEquals(A, a.getObjectId());
463 assertEquals(B, b.getObjectId());
464 }
465
466 @Test
467 public void testGetRefs_TagsOnly_AllLoose() throws IOException {
468 Map<String, Ref> tags;
469 Ref a;
470
471 writeLooseRef("refs/heads/A", A);
472 writeLooseRef("refs/tags/v1.0", v1_0);
473
474 tags = refdir.getRefs(R_TAGS);
475 assertEquals(1, tags.size());
476
477 a = tags.get("v1.0");
478
479 assertEquals("refs/tags/v1.0", a.getName());
480 assertEquals(v1_0, a.getObjectId());
481 }
482
483 @Test
484 public void testGetRefs_LooseSortedCorrectly() throws IOException {
485 Map<String, Ref> refs;
486
487 writeLooseRef("refs/heads/project1/A", A);
488 writeLooseRef("refs/heads/project1-B", B);
489
490 refs = refdir.getRefs(RefDatabase.ALL);
491 assertEquals(2, refs.size());
492 assertEquals(A, refs.get("refs/heads/project1/A").getObjectId());
493 assertEquals(B, refs.get("refs/heads/project1-B").getObjectId());
494 }
495
496 @Test
497 public void testGetRefs_LooseSorting_Bug_348834() throws IOException {
498 Map<String, Ref> refs;
499
500 writeLooseRef("refs/heads/my/a+b", A);
501 writeLooseRef("refs/heads/my/a/b/c", B);
502
503 final int[] count = new int[1];
504
505 ListenerHandle listener = Repository.getGlobalListenerList()
506 .addRefsChangedListener(new RefsChangedListener() {
507
508 public void onRefsChanged(RefsChangedEvent event) {
509 count[0]++;
510 }
511 });
512
513 refs = refdir.getRefs(RefDatabase.ALL);
514 refs = refdir.getRefs(RefDatabase.ALL);
515 listener.remove();
516 assertEquals(1, count[0]);
517 assertEquals(2, refs.size());
518 assertEquals(A, refs.get("refs/heads/my/a+b").getObjectId());
519 assertEquals(B, refs.get("refs/heads/my/a/b/c").getObjectId());
520
521 }
522
523 @Test
524 public void testGetRefs_TagsOnly_AllPacked() throws IOException {
525 Map<String, Ref> tags;
526 Ref a;
527
528 deleteLooseRef(HEAD);
529 writePackedRef("refs/tags/v1.0", v1_0);
530
531 tags = refdir.getRefs(R_TAGS);
532 assertEquals(1, tags.size());
533
534 a = tags.get("v1.0");
535
536 assertEquals("refs/tags/v1.0", a.getName());
537 assertEquals(v1_0, a.getObjectId());
538 }
539
540 @Test
541 public void testGetRefs_DiscoversNewLoose1() throws IOException {
542 Map<String, Ref> orig, next;
543 Ref orig_r, next_r;
544
545 writeLooseRef("refs/heads/master", A);
546 orig = refdir.getRefs(RefDatabase.ALL);
547
548 writeLooseRef("refs/heads/next", B);
549 next = refdir.getRefs(RefDatabase.ALL);
550
551 assertEquals(2, orig.size());
552 assertEquals(3, next.size());
553
554 assertFalse(orig.containsKey("refs/heads/next"));
555 assertTrue(next.containsKey("refs/heads/next"));
556
557 orig_r = orig.get("refs/heads/master");
558 next_r = next.get("refs/heads/master");
559 assertEquals(A, orig_r.getObjectId());
560 assertSame("uses cached instance", orig_r, next_r);
561 assertSame("same HEAD", orig_r, orig.get(HEAD).getTarget());
562 assertSame("same HEAD", orig_r, next.get(HEAD).getTarget());
563
564 next_r = next.get("refs/heads/next");
565 assertSame(LOOSE, next_r.getStorage());
566 assertEquals(B, next_r.getObjectId());
567 }
568
569 @Test
570 public void testGetRefs_DiscoversNewLoose2() throws IOException {
571 Map<String, Ref> orig, next, news;
572
573 writeLooseRef("refs/heads/pu", A);
574 orig = refdir.getRefs(RefDatabase.ALL);
575
576 writeLooseRef("refs/heads/new/B", B);
577 news = refdir.getRefs("refs/heads/new/");
578 next = refdir.getRefs(RefDatabase.ALL);
579
580 assertEquals(1, orig.size());
581 assertEquals(2, next.size());
582 assertEquals(1, news.size());
583
584 assertTrue(orig.containsKey("refs/heads/pu"));
585 assertTrue(next.containsKey("refs/heads/pu"));
586 assertFalse(news.containsKey("refs/heads/pu"));
587
588 assertFalse(orig.containsKey("refs/heads/new/B"));
589 assertTrue(next.containsKey("refs/heads/new/B"));
590 assertTrue(news.containsKey("B"));
591 }
592
593 @Test
594 public void testGetRefs_DiscoversModifiedLoose() throws IOException {
595 Map<String, Ref> all;
596
597 writeLooseRef("refs/heads/master", A);
598 all = refdir.getRefs(RefDatabase.ALL);
599 assertEquals(A, all.get(HEAD).getObjectId());
600
601 writeLooseRef("refs/heads/master", B);
602 all = refdir.getRefs(RefDatabase.ALL);
603 assertEquals(B, all.get(HEAD).getObjectId());
604 }
605
606 @Test
607 public void testGetRef_DiscoversModifiedLoose() throws IOException {
608 Map<String, Ref> all;
609
610 writeLooseRef("refs/heads/master", A);
611 all = refdir.getRefs(RefDatabase.ALL);
612 assertEquals(A, all.get(HEAD).getObjectId());
613
614 writeLooseRef("refs/heads/master", B);
615
616 Ref master = refdir.getRef("refs/heads/master");
617 assertEquals(B, master.getObjectId());
618 }
619
620 @Test
621 public void testGetRefs_DiscoversDeletedLoose1() throws IOException {
622 Map<String, Ref> orig, next;
623 Ref orig_r, next_r;
624
625 writeLooseRef("refs/heads/B", B);
626 writeLooseRef("refs/heads/master", A);
627 orig = refdir.getRefs(RefDatabase.ALL);
628
629 deleteLooseRef("refs/heads/B");
630 next = refdir.getRefs(RefDatabase.ALL);
631
632 assertEquals(3, orig.size());
633 assertEquals(2, next.size());
634
635 assertTrue(orig.containsKey("refs/heads/B"));
636 assertFalse(next.containsKey("refs/heads/B"));
637
638 orig_r = orig.get("refs/heads/master");
639 next_r = next.get("refs/heads/master");
640 assertEquals(A, orig_r.getObjectId());
641 assertSame("uses cached instance", orig_r, next_r);
642 assertSame("same HEAD", orig_r, orig.get(HEAD).getTarget());
643 assertSame("same HEAD", orig_r, next.get(HEAD).getTarget());
644
645 orig_r = orig.get("refs/heads/B");
646 assertSame(LOOSE, orig_r.getStorage());
647 assertEquals(B, orig_r.getObjectId());
648 }
649
650 @Test
651 public void testGetRef_DiscoversDeletedLoose() throws IOException {
652 Map<String, Ref> all;
653
654 writeLooseRef("refs/heads/master", A);
655 all = refdir.getRefs(RefDatabase.ALL);
656 assertEquals(A, all.get(HEAD).getObjectId());
657
658 deleteLooseRef("refs/heads/master");
659 assertNull(refdir.getRef("refs/heads/master"));
660 assertTrue(refdir.getRefs(RefDatabase.ALL).isEmpty());
661 }
662
663 @Test
664 public void testGetRefs_DiscoversDeletedLoose2() throws IOException {
665 Map<String, Ref> orig, next;
666
667 writeLooseRef("refs/heads/master", A);
668 writeLooseRef("refs/heads/pu", B);
669 orig = refdir.getRefs(RefDatabase.ALL);
670
671 deleteLooseRef("refs/heads/pu");
672 next = refdir.getRefs(RefDatabase.ALL);
673
674 assertEquals(3, orig.size());
675 assertEquals(2, next.size());
676
677 assertTrue(orig.containsKey("refs/heads/pu"));
678 assertFalse(next.containsKey("refs/heads/pu"));
679 }
680
681 @Test
682 public void testGetRefs_DiscoversDeletedLoose3() throws IOException {
683 Map<String, Ref> orig, next;
684
685 writeLooseRef("refs/heads/master", A);
686 writeLooseRef("refs/heads/next", B);
687 writeLooseRef("refs/heads/pu", B);
688 writeLooseRef("refs/tags/v1.0", v1_0);
689 orig = refdir.getRefs(RefDatabase.ALL);
690
691 deleteLooseRef("refs/heads/pu");
692 deleteLooseRef("refs/heads/next");
693 next = refdir.getRefs(RefDatabase.ALL);
694
695 assertEquals(5, orig.size());
696 assertEquals(3, next.size());
697
698 assertTrue(orig.containsKey("refs/heads/pu"));
699 assertTrue(orig.containsKey("refs/heads/next"));
700 assertFalse(next.containsKey("refs/heads/pu"));
701 assertFalse(next.containsKey("refs/heads/next"));
702 }
703
704 @Test
705 public void testGetRefs_DiscoversDeletedLoose4() throws IOException {
706 Map<String, Ref> orig, next;
707 Ref orig_r, next_r;
708
709 writeLooseRef("refs/heads/B", B);
710 writeLooseRef("refs/heads/master", A);
711 orig = refdir.getRefs(RefDatabase.ALL);
712
713 deleteLooseRef("refs/heads/master");
714 next = refdir.getRefs("refs/heads/");
715
716 assertEquals(3, orig.size());
717 assertEquals(1, next.size());
718
719 assertTrue(orig.containsKey("refs/heads/B"));
720 assertTrue(orig.containsKey("refs/heads/master"));
721 assertTrue(next.containsKey("B"));
722 assertFalse(next.containsKey("master"));
723
724 orig_r = orig.get("refs/heads/B");
725 next_r = next.get("B");
726 assertEquals(B, orig_r.getObjectId());
727 assertSame("uses cached instance", orig_r, next_r);
728 }
729
730 @Test
731 public void testGetRefs_DiscoversDeletedLoose5() throws IOException {
732 Map<String, Ref> orig, next;
733
734 writeLooseRef("refs/heads/master", A);
735 writeLooseRef("refs/heads/pu", B);
736 orig = refdir.getRefs(RefDatabase.ALL);
737
738 deleteLooseRef("refs/heads/pu");
739 writeLooseRef("refs/tags/v1.0", v1_0);
740 next = refdir.getRefs(RefDatabase.ALL);
741
742 assertEquals(3, orig.size());
743 assertEquals(3, next.size());
744
745 assertTrue(orig.containsKey("refs/heads/pu"));
746 assertFalse(orig.containsKey("refs/tags/v1.0"));
747 assertFalse(next.containsKey("refs/heads/pu"));
748 assertTrue(next.containsKey("refs/tags/v1.0"));
749 }
750
751 @Test
752 public void testGetRefs_SkipsLockFiles() throws IOException {
753 Map<String, Ref> all;
754
755 writeLooseRef("refs/heads/master", A);
756 writeLooseRef("refs/heads/pu.lock", B);
757 all = refdir.getRefs(RefDatabase.ALL);
758
759 assertEquals(2, all.size());
760
761 assertTrue(all.containsKey(HEAD));
762 assertTrue(all.containsKey("refs/heads/master"));
763 assertFalse(all.containsKey("refs/heads/pu.lock"));
764 }
765
766 @Test
767 public void testGetRefs_CycleInSymbolicRef() throws IOException {
768 Map<String, Ref> all;
769 Ref r;
770
771 writeLooseRef("refs/1", "ref: refs/2\n");
772 writeLooseRef("refs/2", "ref: refs/3\n");
773 writeLooseRef("refs/3", "ref: refs/4\n");
774 writeLooseRef("refs/4", "ref: refs/5\n");
775 writeLooseRef("refs/5", "ref: refs/end\n");
776 writeLooseRef("refs/end", A);
777
778 all = refdir.getRefs(RefDatabase.ALL);
779 r = all.get("refs/1");
780 assertNotNull("has 1", r);
781
782 assertEquals("refs/1", r.getName());
783 assertEquals(A, r.getObjectId());
784 assertTrue(r.isSymbolic());
785
786 r = r.getTarget();
787 assertEquals("refs/2", r.getName());
788 assertEquals(A, r.getObjectId());
789 assertTrue(r.isSymbolic());
790
791 r = r.getTarget();
792 assertEquals("refs/3", r.getName());
793 assertEquals(A, r.getObjectId());
794 assertTrue(r.isSymbolic());
795
796 r = r.getTarget();
797 assertEquals("refs/4", r.getName());
798 assertEquals(A, r.getObjectId());
799 assertTrue(r.isSymbolic());
800
801 r = r.getTarget();
802 assertEquals("refs/5", r.getName());
803 assertEquals(A, r.getObjectId());
804 assertTrue(r.isSymbolic());
805
806 r = r.getTarget();
807 assertEquals("refs/end", r.getName());
808 assertEquals(A, r.getObjectId());
809 assertFalse(r.isSymbolic());
810
811 writeLooseRef("refs/5", "ref: refs/6\n");
812 writeLooseRef("refs/6", "ref: refs/end\n");
813 all = refdir.getRefs(RefDatabase.ALL);
814 r = all.get("refs/1");
815 assertNull("mising 1 due to cycle", r);
816 }
817
818 @Test
819 public void testGetRefs_PackedNotPeeled_Sorted() throws IOException {
820 Map<String, Ref> all;
821
822 writePackedRefs("" +
823 A.name() + " refs/heads/master\n" +
824 B.name() + " refs/heads/other\n" +
825 v1_0.name() + " refs/tags/v1.0\n");
826 all = refdir.getRefs(RefDatabase.ALL);
827
828 assertEquals(4, all.size());
829 final Ref head = all.get(HEAD);
830 final Ref master = all.get("refs/heads/master");
831 final Ref other = all.get("refs/heads/other");
832 final Ref tag = all.get("refs/tags/v1.0");
833
834 assertEquals(A, master.getObjectId());
835 assertFalse(master.isPeeled());
836 assertNull(master.getPeeledObjectId());
837
838 assertEquals(B, other.getObjectId());
839 assertFalse(other.isPeeled());
840 assertNull(other.getPeeledObjectId());
841
842 assertSame(master, head.getTarget());
843 assertEquals(A, head.getObjectId());
844 assertFalse(head.isPeeled());
845 assertNull(head.getPeeledObjectId());
846
847 assertEquals(v1_0, tag.getObjectId());
848 assertFalse(tag.isPeeled());
849 assertNull(tag.getPeeledObjectId());
850 }
851
852 @Test
853 public void testGetRef_PackedNotPeeled_WrongSort() throws IOException {
854 writePackedRefs("" +
855 v1_0.name() + " refs/tags/v1.0\n" +
856 B.name() + " refs/heads/other\n" +
857 A.name() + " refs/heads/master\n");
858
859 final Ref head = refdir.getRef(HEAD);
860 final Ref master = refdir.getRef("refs/heads/master");
861 final Ref other = refdir.getRef("refs/heads/other");
862 final Ref tag = refdir.getRef("refs/tags/v1.0");
863
864 assertEquals(A, master.getObjectId());
865 assertFalse(master.isPeeled());
866 assertNull(master.getPeeledObjectId());
867
868 assertEquals(B, other.getObjectId());
869 assertFalse(other.isPeeled());
870 assertNull(other.getPeeledObjectId());
871
872 assertSame(master, head.getTarget());
873 assertEquals(A, head.getObjectId());
874 assertFalse(head.isPeeled());
875 assertNull(head.getPeeledObjectId());
876
877 assertEquals(v1_0, tag.getObjectId());
878 assertFalse(tag.isPeeled());
879 assertNull(tag.getPeeledObjectId());
880 }
881
882 @Test
883 public void testGetRefs_PackedWithPeeled() throws IOException {
884 Map<String, Ref> all;
885
886 writePackedRefs("# pack-refs with: peeled \n" +
887 A.name() + " refs/heads/master\n" +
888 B.name() + " refs/heads/other\n" +
889 v1_0.name() + " refs/tags/v1.0\n" +
890 "^" + v1_0.getObject().name() + "\n");
891 all = refdir.getRefs(RefDatabase.ALL);
892
893 assertEquals(4, all.size());
894 final Ref head = all.get(HEAD);
895 final Ref master = all.get("refs/heads/master");
896 final Ref other = all.get("refs/heads/other");
897 final Ref tag = all.get("refs/tags/v1.0");
898
899 assertEquals(A, master.getObjectId());
900 assertTrue(master.isPeeled());
901 assertNull(master.getPeeledObjectId());
902
903 assertEquals(B, other.getObjectId());
904 assertTrue(other.isPeeled());
905 assertNull(other.getPeeledObjectId());
906
907 assertSame(master, head.getTarget());
908 assertEquals(A, head.getObjectId());
909 assertTrue(head.isPeeled());
910 assertNull(head.getPeeledObjectId());
911
912 assertEquals(v1_0, tag.getObjectId());
913 assertTrue(tag.isPeeled());
914 assertEquals(v1_0.getObject(), tag.getPeeledObjectId());
915 }
916
917 @Test
918 public void test_repack() throws Exception {
919 Map<String, Ref> all;
920
921 writePackedRefs("# pack-refs with: peeled \n" +
922 A.name() + " refs/heads/master\n" +
923 B.name() + " refs/heads/other\n" +
924 v1_0.name() + " refs/tags/v1.0\n" +
925 "^" + v1_0.getObject().name() + "\n");
926 all = refdir.getRefs(RefDatabase.ALL);
927
928 assertEquals(4, all.size());
929 assertEquals(Storage.LOOSE, all.get(HEAD).getStorage());
930 assertEquals(Storage.PACKED, all.get("refs/heads/master").getStorage());
931 assertEquals(A.getId(), all.get("refs/heads/master").getObjectId());
932 assertEquals(Storage.PACKED, all.get("refs/heads/other").getStorage());
933 assertEquals(Storage.PACKED, all.get("refs/tags/v1.0").getStorage());
934
935 repo.update("refs/heads/master", B.getId());
936 RevTag v0_1 = repo.tag("v0.1", A);
937 repo.update("refs/tags/v0.1", v0_1);
938
939 all = refdir.getRefs(RefDatabase.ALL);
940 assertEquals(5, all.size());
941 assertEquals(Storage.LOOSE, all.get(HEAD).getStorage());
942
943 assertEquals(Storage.LOOSE, all.get("refs/heads/master")
944 .getStorage());
945 assertEquals(B.getId(), all.get("refs/heads/master").getObjectId());
946 assertEquals(Storage.PACKED, all.get("refs/heads/other").getStorage());
947 assertEquals(Storage.PACKED, all.get("refs/tags/v1.0").getStorage());
948 assertEquals(Storage.LOOSE, all.get("refs/tags/v0.1").getStorage());
949 assertEquals(v0_1.getId(), all.get("refs/tags/v0.1").getObjectId());
950
951 all = refdir.getRefs(RefDatabase.ALL);
952 refdir.pack(new ArrayList<String>(all.keySet()));
953
954 all = refdir.getRefs(RefDatabase.ALL);
955 assertEquals(5, all.size());
956 assertEquals(Storage.LOOSE, all.get(HEAD).getStorage());
957
958 assertEquals(Storage.PACKED, all.get("refs/heads/master").getStorage());
959 assertEquals(B.getId(), all.get("refs/heads/master").getObjectId());
960 assertEquals(Storage.PACKED, all.get("refs/heads/other").getStorage());
961 assertEquals(Storage.PACKED, all.get("refs/tags/v1.0").getStorage());
962 assertEquals(Storage.PACKED, all.get("refs/tags/v0.1").getStorage());
963 assertEquals(v0_1.getId(), all.get("refs/tags/v0.1").getObjectId());
964 }
965
966 @Test
967 public void testGetRef_EmptyDatabase() throws IOException {
968 Ref r;
969
970 r = refdir.getRef(HEAD);
971 assertTrue(r.isSymbolic());
972 assertSame(LOOSE, r.getStorage());
973 assertEquals("refs/heads/master", r.getTarget().getName());
974 assertSame(NEW, r.getTarget().getStorage());
975 assertNull(r.getTarget().getObjectId());
976
977 assertNull(refdir.getRef("refs/heads/master"));
978 assertNull(refdir.getRef("refs/tags/v1.0"));
979 assertNull(refdir.getRef("FETCH_HEAD"));
980 assertNull(refdir.getRef("NOT.A.REF.NAME"));
981 assertNull(refdir.getRef("master"));
982 assertNull(refdir.getRef("v1.0"));
983 }
984
985 @Test
986 public void testGetRef_FetchHead() throws IOException {
987
988
989
990 write(new File(diskRepo.getDirectory(), "FETCH_HEAD"), A.name()
991 + "\tnot-for-merge"
992 + "\tbranch 'master' of git://egit.eclipse.org/jgit\n");
993
994 Ref r = refdir.getRef("FETCH_HEAD");
995 assertFalse(r.isSymbolic());
996 assertEquals(A, r.getObjectId());
997 assertEquals("FETCH_HEAD", r.getName());
998 assertFalse(r.isPeeled());
999 assertNull(r.getPeeledObjectId());
1000 }
1001
1002 @Test
1003 public void testGetRef_AnyHeadWithGarbage() throws IOException {
1004 write(new File(diskRepo.getDirectory(), "refs/heads/A"), A.name()
1005 + "012345 . this is not a standard reference\n"
1006 + "#and even more junk\n");
1007
1008 Ref r = refdir.getRef("refs/heads/A");
1009 assertFalse(r.isSymbolic());
1010 assertEquals(A, r.getObjectId());
1011 assertEquals("refs/heads/A", r.getName());
1012 assertFalse(r.isPeeled());
1013 assertNull(r.getPeeledObjectId());
1014 }
1015
1016 @Test
1017 public void testGetRefs_CorruptSymbolicReference() throws IOException {
1018 String name = "refs/heads/A";
1019 writeLooseRef(name, "ref: \n");
1020 assertTrue(refdir.getRefs(RefDatabase.ALL).isEmpty());
1021 }
1022
1023 @Test
1024 public void testGetRef_CorruptSymbolicReference() throws IOException {
1025 String name = "refs/heads/A";
1026 writeLooseRef(name, "ref: \n");
1027 try {
1028 refdir.getRef(name);
1029 fail("read an invalid reference");
1030 } catch (IOException err) {
1031 String msg = err.getMessage();
1032 assertEquals("Not a ref: " + name + ": ref:", msg);
1033 }
1034 }
1035
1036 @Test
1037 public void testGetRefs_CorruptObjectIdReference() throws IOException {
1038 String name = "refs/heads/A";
1039 String content = "zoo" + A.name();
1040 writeLooseRef(name, content + "\n");
1041 assertTrue(refdir.getRefs(RefDatabase.ALL).isEmpty());
1042 }
1043
1044 @Test
1045 public void testGetRef_CorruptObjectIdReference() throws IOException {
1046 String name = "refs/heads/A";
1047 String content = "zoo" + A.name();
1048 writeLooseRef(name, content + "\n");
1049 try {
1050 refdir.getRef(name);
1051 fail("read an invalid reference");
1052 } catch (IOException err) {
1053 String msg = err.getMessage();
1054 assertEquals("Not a ref: " + name + ": " + content, msg);
1055 }
1056 }
1057
1058 @Test
1059 public void testIsNameConflicting() throws IOException {
1060 writeLooseRef("refs/heads/a/b", A);
1061 writePackedRef("refs/heads/q", B);
1062
1063
1064 assertTrue(refdir.isNameConflicting("refs"));
1065 assertTrue(refdir.isNameConflicting("refs/heads"));
1066 assertTrue(refdir.isNameConflicting("refs/heads/a"));
1067
1068
1069 assertFalse(refdir.isNameConflicting("refs/heads/a/b"));
1070
1071
1072 assertFalse(refdir.isNameConflicting("refs/heads/a/d"));
1073 assertFalse(refdir.isNameConflicting("refs/heads/master"));
1074
1075
1076 assertTrue(refdir.isNameConflicting("refs/heads/a/b/c"));
1077 assertTrue(refdir.isNameConflicting("refs/heads/q/master"));
1078 }
1079
1080 @Test
1081 public void testPeelLooseTag() throws IOException {
1082 writeLooseRef("refs/tags/v1_0", v1_0);
1083 writeLooseRef("refs/tags/current", "ref: refs/tags/v1_0\n");
1084
1085 final Ref tag = refdir.getRef("refs/tags/v1_0");
1086 final Ref cur = refdir.getRef("refs/tags/current");
1087
1088 assertEquals(v1_0, tag.getObjectId());
1089 assertFalse(tag.isSymbolic());
1090 assertFalse(tag.isPeeled());
1091 assertNull(tag.getPeeledObjectId());
1092
1093 assertEquals(v1_0, cur.getObjectId());
1094 assertTrue(cur.isSymbolic());
1095 assertFalse(cur.isPeeled());
1096 assertNull(cur.getPeeledObjectId());
1097
1098 final Ref tag_p = refdir.peel(tag);
1099 final Ref cur_p = refdir.peel(cur);
1100
1101 assertNotSame(tag, tag_p);
1102 assertFalse(tag_p.isSymbolic());
1103 assertTrue(tag_p.isPeeled());
1104 assertEquals(v1_0, tag_p.getObjectId());
1105 assertEquals(v1_0.getObject(), tag_p.getPeeledObjectId());
1106 assertSame(tag_p, refdir.peel(tag_p));
1107
1108 assertNotSame(cur, cur_p);
1109 assertEquals("refs/tags/current", cur_p.getName());
1110 assertTrue(cur_p.isSymbolic());
1111 assertEquals("refs/tags/v1_0", cur_p.getTarget().getName());
1112 assertTrue(cur_p.isPeeled());
1113 assertEquals(v1_0, cur_p.getObjectId());
1114 assertEquals(v1_0.getObject(), cur_p.getPeeledObjectId());
1115
1116
1117
1118 final Ref tag_p2 = refdir.getRef("refs/tags/v1_0");
1119 assertFalse(tag_p2.isSymbolic());
1120 assertTrue(tag_p2.isPeeled());
1121 assertEquals(v1_0, tag_p2.getObjectId());
1122 assertEquals(v1_0.getObject(), tag_p2.getPeeledObjectId());
1123
1124 assertSame(tag_p2, refdir.getRef("refs/tags/v1_0"));
1125 assertSame(tag_p2, refdir.getRef("refs/tags/current").getTarget());
1126 assertSame(tag_p2, refdir.peel(tag_p2));
1127 }
1128
1129 @Test
1130 public void testPeelCommit() throws IOException {
1131 writeLooseRef("refs/heads/master", A);
1132
1133 Ref master = refdir.getRef("refs/heads/master");
1134 assertEquals(A, master.getObjectId());
1135 assertFalse(master.isPeeled());
1136 assertNull(master.getPeeledObjectId());
1137
1138 Ref master_p = refdir.peel(master);
1139 assertNotSame(master, master_p);
1140 assertEquals(A, master_p.getObjectId());
1141 assertTrue(master_p.isPeeled());
1142 assertNull(master_p.getPeeledObjectId());
1143
1144
1145
1146 Ref master_p2 = refdir.getRef("refs/heads/master");
1147 assertNotSame(master, master_p2);
1148 assertEquals(A, master_p2.getObjectId());
1149 assertTrue(master_p2.isPeeled());
1150 assertNull(master_p2.getPeeledObjectId());
1151 assertSame(master_p2, refdir.peel(master_p2));
1152 }
1153
1154 @Test
1155 public void testRefsChangedStackOverflow() throws Exception {
1156 final FileRepository newRepo = createBareRepository();
1157 final RefDatabase refDb = newRepo.getRefDatabase();
1158 File packedRefs = new File(newRepo.getDirectory(), "packed-refs");
1159 assertTrue(packedRefs.createNewFile());
1160 final AtomicReference<StackOverflowError> error = new AtomicReference<StackOverflowError>();
1161 final AtomicReference<IOException> exception = new AtomicReference<IOException>();
1162 final AtomicInteger changeCount = new AtomicInteger();
1163 newRepo.getListenerList().addRefsChangedListener(
1164 new RefsChangedListener() {
1165
1166 public void onRefsChanged(RefsChangedEvent event) {
1167 try {
1168 refDb.getRefs("ref");
1169 changeCount.incrementAndGet();
1170 } catch (StackOverflowError soe) {
1171 error.set(soe);
1172 } catch (IOException ioe) {
1173 exception.set(ioe);
1174 }
1175 }
1176 });
1177 refDb.getRefs("ref");
1178 refDb.getRefs("ref");
1179 assertNull(error.get());
1180 assertNull(exception.get());
1181 assertEquals(1, changeCount.get());
1182 }
1183
1184 @Test
1185 public void testBatchRefUpdateSimpleNoForce() throws IOException {
1186 writeLooseRef("refs/heads/master", A);
1187 writeLooseRef("refs/heads/masters", B);
1188 List<ReceiveCommand> commands = Arrays.asList(
1189 newCommand(A, B, "refs/heads/master",
1190 ReceiveCommand.Type.UPDATE),
1191 newCommand(B, A, "refs/heads/masters",
1192 ReceiveCommand.Type.UPDATE_NONFASTFORWARD));
1193 BatchRefUpdate batchUpdate = refdir.newBatchUpdate();
1194 batchUpdate.addCommand(commands);
1195 batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
1196 Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
1197 assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
1198 assertEquals(ReceiveCommand.Result.REJECTED_NONFASTFORWARD, commands
1199 .get(1).getResult());
1200 assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
1201 .keySet().toString());
1202 assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
1203 assertEquals(B.getId(), refs.get("refs/heads/masters").getObjectId());
1204 }
1205
1206 @Test
1207 public void testBatchRefUpdateSimpleForce() throws IOException {
1208 writeLooseRef("refs/heads/master", A);
1209 writeLooseRef("refs/heads/masters", B);
1210 List<ReceiveCommand> commands = Arrays.asList(
1211 newCommand(A, B, "refs/heads/master",
1212 ReceiveCommand.Type.UPDATE),
1213 newCommand(B, A, "refs/heads/masters",
1214 ReceiveCommand.Type.UPDATE_NONFASTFORWARD));
1215 BatchRefUpdate batchUpdate = refdir.newBatchUpdate();
1216 batchUpdate.setAllowNonFastForwards(true);
1217 batchUpdate.addCommand(commands);
1218 batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
1219 Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
1220 assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
1221 assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
1222 assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
1223 .keySet().toString());
1224 assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
1225 assertEquals(A.getId(), refs.get("refs/heads/masters").getObjectId());
1226 }
1227
1228 @Test
1229 public void testBatchRefUpdateNonFastForwardDoesNotDoExpensiveMergeCheck()
1230 throws IOException {
1231 writeLooseRef("refs/heads/master", B);
1232 List<ReceiveCommand> commands = Arrays.asList(
1233 newCommand(B, A, "refs/heads/master",
1234 ReceiveCommand.Type.UPDATE_NONFASTFORWARD));
1235 BatchRefUpdate batchUpdate = refdir.newBatchUpdate();
1236 batchUpdate.setAllowNonFastForwards(true);
1237 batchUpdate.addCommand(commands);
1238 batchUpdate.execute(new RevWalk(diskRepo) {
1239 @Override
1240 public boolean isMergedInto(RevCommit base, RevCommit tip) {
1241 throw new AssertionError("isMergedInto() should not be called");
1242 }
1243 }, new StrictWorkMonitor());
1244 Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
1245 assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
1246 assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
1247 }
1248
1249 @Test
1250 public void testBatchRefUpdateConflict() throws IOException {
1251 writeLooseRef("refs/heads/master", A);
1252 writeLooseRef("refs/heads/masters", B);
1253 List<ReceiveCommand> commands = Arrays.asList(
1254 newCommand(A, B, "refs/heads/master",
1255 ReceiveCommand.Type.UPDATE),
1256 newCommand(null, A, "refs/heads/master/x",
1257 ReceiveCommand.Type.CREATE),
1258 newCommand(null, A, "refs/heads", ReceiveCommand.Type.CREATE));
1259 BatchRefUpdate batchUpdate = refdir.newBatchUpdate();
1260 batchUpdate.setAllowNonFastForwards(true);
1261 batchUpdate.addCommand(commands);
1262 batchUpdate
1263 .execute(new RevWalk(diskRepo), NullProgressMonitor.INSTANCE);
1264 Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
1265 assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
1266 assertEquals(ReceiveCommand.Result.LOCK_FAILURE, commands.get(1)
1267 .getResult());
1268 assertEquals(ReceiveCommand.Result.LOCK_FAILURE, commands.get(2)
1269 .getResult());
1270 assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
1271 .keySet().toString());
1272 assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
1273 assertEquals(B.getId(), refs.get("refs/heads/masters").getObjectId());
1274 }
1275
1276 @Test
1277 public void testBatchRefUpdateConflictThanksToDelete() throws IOException {
1278 writeLooseRef("refs/heads/master", A);
1279 writeLooseRef("refs/heads/masters", B);
1280 List<ReceiveCommand> commands = Arrays.asList(
1281 newCommand(A, B, "refs/heads/master",
1282 ReceiveCommand.Type.UPDATE),
1283 newCommand(null, A, "refs/heads/masters/x",
1284 ReceiveCommand.Type.CREATE),
1285 newCommand(B, null, "refs/heads/masters",
1286 ReceiveCommand.Type.DELETE));
1287 BatchRefUpdate batchUpdate = refdir.newBatchUpdate();
1288 batchUpdate.setAllowNonFastForwards(true);
1289 batchUpdate.addCommand(commands);
1290 batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
1291 Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
1292 assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
1293 assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
1294 assertEquals(ReceiveCommand.Result.OK, commands.get(2).getResult());
1295 assertEquals("[HEAD, refs/heads/master, refs/heads/masters/x]", refs
1296 .keySet().toString());
1297 assertEquals(A.getId(), refs.get("refs/heads/masters/x").getObjectId());
1298 }
1299
1300 private static ReceiveCommand newCommand(RevCommit a, RevCommit b,
1301 String string, Type update) {
1302 return new ReceiveCommand(a != null ? a.getId() : null,
1303 b != null ? b.getId() : null, string, update);
1304 }
1305
1306 private void writeLooseRef(String name, AnyObjectId id) throws IOException {
1307 writeLooseRef(name, id.name() + "\n");
1308 }
1309
1310 private void writeLooseRef(String name, String content) throws IOException {
1311 write(new File(diskRepo.getDirectory(), name), content);
1312 }
1313
1314 private void writePackedRef(String name, AnyObjectId id) throws IOException {
1315 writePackedRefs(id.name() + " " + name + "\n");
1316 }
1317
1318 private void writePackedRefs(String content) throws IOException {
1319 File pr = new File(diskRepo.getDirectory(), "packed-refs");
1320 write(pr, content);
1321
1322 final long now = System.currentTimeMillis();
1323 final int oneHourAgo = 3600 * 1000;
1324 pr.setLastModified(now - oneHourAgo);
1325 }
1326
1327 private void deleteLooseRef(String name) {
1328 File path = new File(diskRepo.getDirectory(), name);
1329 assertTrue("deleted " + name, path.delete());
1330 }
1331
1332 private static final class StrictWorkMonitor implements ProgressMonitor {
1333 private int lastWork, totalWork;
1334
1335 public void start(int totalTasks) {
1336
1337 }
1338
1339 public void beginTask(String title, int totalWork) {
1340 this.totalWork = totalWork;
1341 lastWork = 0;
1342 }
1343
1344 public void update(int completed) {
1345 lastWork += completed;
1346 }
1347
1348 public void endTask() {
1349 assertEquals("Units of work recorded", totalWork, lastWork);
1350 }
1351
1352 public boolean isCancelled() {
1353 return false;
1354 }
1355 }
1356 }