]> source.dussan.org Git - jgit.git/commitdiff
reftable: fix lookup by ID in merged reftables 62/151062/3
authorHan-Wen Nienhuys <hanwen@google.com>
Sun, 13 Oct 2019 17:21:06 +0000 (19:21 +0200)
committerHan-Wen Nienhuys <hanwen@google.com>
Wed, 16 Oct 2019 13:15:55 +0000 (15:15 +0200)
On changing a ref, the old SHA1 is not updated in the object => ref
mapping. This means search by object ID may still turn up a ref from
deeper within the stack. To fix this, check all refs produced by the
merged iterator against the merged reftables.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Change-Id: I41e9cd395b0608eedeeaead0a9fd997238d747c9

org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java

index c20db7b96b1e155d5b50d71340eb65a657311cb5..5f5ab72671a4f23cfc901350f922f6933318afbb 100644 (file)
@@ -187,6 +187,19 @@ public class MergedReftableTest {
                }
        }
 
+       @Test
+       public void tableByIDDeletion() throws IOException {
+               List<Ref> delta1 = Arrays.asList(
+                               ref("refs/heads/apple", 1),
+                               ref("refs/heads/master", 2));
+               List<Ref> delta2 = Arrays.asList(ref("refs/heads/master", 3));
+
+               MergedReftable mr = merge(write(delta1), write(delta2));
+               try (RefCursor rc = mr.byObjectId(id(2))) {
+                       assertFalse(rc.next());
+               }
+       }
+
        @SuppressWarnings("boxing")
        @Test
        public void fourTableScan() throws IOException {
index a4394066eac50f704ab5d4a6d22cbfa78e9b1c0b..4de5e392f9d8b3051ce2a28016dbd9e84d8d4473 100644 (file)
@@ -131,7 +131,7 @@ public class MergedReftable extends Reftable {
        /** {@inheritDoc} */
        @Override
        public RefCursor byObjectId(AnyObjectId name) throws IOException {
-               MergedRefCursor m = new MergedRefCursor();
+               MergedRefCursor m = new FilteringMergedRefCursor(name);
                for (int i = 0; i < tables.length; i++) {
                        m.add(new RefQueueEntry(tables[i].byObjectId(name), i));
                }
@@ -250,6 +250,42 @@ public class MergedReftable extends Reftable {
                }
        }
 
+       private class FilteringMergedRefCursor extends MergedRefCursor {
+               final AnyObjectId filterId;
+               Ref filteredRef;
+
+               FilteringMergedRefCursor(AnyObjectId id) {
+                       filterId = id;
+                       filteredRef = null;
+               }
+
+               @Override
+               public Ref getRef() {
+                       return filteredRef;
+               }
+
+               @Override
+               public boolean next() throws IOException {
+                       for (;;) {
+                               boolean ok = super.next();
+                               if (!ok) {
+                                       return false;
+                               }
+
+                               String name = super.getRef().getName();
+
+                               try (RefCursor c = seekRef(name)) {
+                                       if (c.next()) {
+                                               if (filterId.equals(c.getRef().getObjectId())) {
+                                                       filteredRef = c.getRef();
+                                                       return true;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
        private static class RefQueueEntry {
                static int compare(RefQueueEntry a, RefQueueEntry b) {
                        int cmp = a.name().compareTo(b.name());