summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHan-Wen Nienhuys <hanwen@google.com>2019-10-13 19:21:06 +0200
committerHan-Wen Nienhuys <hanwen@google.com>2019-10-16 15:15:55 +0200
commit218bacdc1f96942701503aa7891707bb3eccc111 (patch)
tree53aaf1a6592b245620f93afc288c8c909e1f972c
parentbca00aa5f464e1bc3aa00d4b757554b54f35ddb2 (diff)
downloadjgit-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
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java38
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());