diff options
author | Han-Wen Nienhuys <hanwen@google.com> | 2019-10-13 19:21:06 +0200 |
---|---|---|
committer | Han-Wen Nienhuys <hanwen@google.com> | 2019-10-16 15:15:55 +0200 |
commit | 218bacdc1f96942701503aa7891707bb3eccc111 (patch) | |
tree | 53aaf1a6592b245620f93afc288c8c909e1f972c | |
parent | bca00aa5f464e1bc3aa00d4b757554b54f35ddb2 (diff) | |
download | jgit-218bacdc1f96942701503aa7891707bb3eccc111.tar.gz jgit-218bacdc1f96942701503aa7891707bb3eccc111.zip |
reftable: fix lookup by ID in merged reftables
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
2 files changed, 50 insertions, 1 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java index c20db7b96b..5f5ab72671 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java @@ -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 { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java index a4394066ea..4de5e392f9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java @@ -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()); |