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
This commit is contained in:
parent
bca00aa5f4
commit
218bacdc1f
|
@ -187,6 +187,19 @@ public void twoTableById() throws IOException {
|
|||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
|
|
@ -131,7 +131,7 @@ public RefCursor seekRefsWithPrefix(String prefix) throws IOException {
|
|||
/** {@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 void close() {
|
|||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
|
Loading…
Reference in New Issue