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