Merge changes from topic 'update-index-ref-decorator'
* changes: RefCursor: Remove unnecessary getUpdateIndex method RefDatabase/Ref: Add versioning to reference database
This commit is contained in:
commit
f5bdb9745f
|
@ -61,6 +61,7 @@
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
@ -134,6 +135,33 @@ public void testCreate() throws IOException {
|
||||||
assertEquals("ref: refs/heads/master\n", read(new File(d, HEAD)));
|
assertEquals("ref: refs/heads/master\n", read(new File(d, HEAD)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
|
public void testVersioningNotImplemented_exactRef() throws IOException {
|
||||||
|
assertFalse(refdir.hasVersioning());
|
||||||
|
|
||||||
|
Ref ref = refdir.exactRef(HEAD);
|
||||||
|
assertNotNull(ref);
|
||||||
|
ref.getUpdateIndex(); // Not implemented on FS
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersioningNotImplemented_getRefs() throws Exception {
|
||||||
|
assertFalse(refdir.hasVersioning());
|
||||||
|
|
||||||
|
RevCommit C = repo.commit().parent(B).create();
|
||||||
|
repo.update("master", C);
|
||||||
|
List<Ref> refs = refdir.getRefs();
|
||||||
|
|
||||||
|
for (Ref ref : refs) {
|
||||||
|
try {
|
||||||
|
ref.getUpdateIndex();
|
||||||
|
fail("FS doesn't implement ref versioning");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRefs_EmptyDatabase() throws IOException {
|
public void testGetRefs_EmptyDatabase() throws IOException {
|
||||||
Map<String, Ref> all;
|
Map<String, Ref> all;
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
package org.eclipse.jgit.internal.storage.reftable;
|
package org.eclipse.jgit.internal.storage.reftable;
|
||||||
|
|
||||||
import static org.eclipse.jgit.lib.Constants.HEAD;
|
import static org.eclipse.jgit.lib.Constants.HEAD;
|
||||||
|
import static org.eclipse.jgit.lib.Constants.MASTER;
|
||||||
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
|
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
|
||||||
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
||||||
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
|
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
|
||||||
|
@ -68,6 +69,7 @@
|
||||||
import org.eclipse.jgit.lib.ObjectIdRef;
|
import org.eclipse.jgit.lib.ObjectIdRef;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.RefComparator;
|
import org.eclipse.jgit.lib.RefComparator;
|
||||||
|
import org.eclipse.jgit.lib.SymbolicRef;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class MergedReftableTest {
|
public class MergedReftableTest {
|
||||||
|
@ -128,6 +130,7 @@ public void oneTableScan() throws IOException {
|
||||||
Ref act = rc.getRef();
|
Ref act = rc.getRef();
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
|
assertEquals(1, act.getUpdateIndex());
|
||||||
}
|
}
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -145,6 +148,7 @@ public void deleteIsHidden() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/master", rc.getRef().getName());
|
assertEquals("refs/heads/master", rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,6 +166,7 @@ public void twoTableSeek() throws IOException {
|
||||||
assertEquals("refs/heads/master", rc.getRef().getName());
|
assertEquals("refs/heads/master", rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +182,7 @@ public void twoTableById() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/master", rc.getRef().getName());
|
assertEquals("refs/heads/master", rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,6 +218,7 @@ public void fourTableScan() throws IOException {
|
||||||
Ref act = rc.getRef();
|
Ref act = rc.getRef();
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -231,9 +238,11 @@ public void scanDuplicates() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/apple", rc.getRef().getName());
|
assertEquals("refs/heads/apple", rc.getRef().getName());
|
||||||
assertEquals(id(3), rc.getRef().getObjectId());
|
assertEquals(id(3), rc.getRef().getObjectId());
|
||||||
|
assertEquals(2000, rc.getRef().getUpdateIndex());
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/banana", rc.getRef().getName());
|
assertEquals("refs/heads/banana", rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
|
assertEquals(1000, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,12 +260,14 @@ public void scanIncludeDeletes() throws IOException {
|
||||||
Ref r = rc.getRef();
|
Ref r = rc.getRef();
|
||||||
assertEquals("refs/heads/master", r.getName());
|
assertEquals("refs/heads/master", r.getName());
|
||||||
assertEquals(id(8), r.getObjectId());
|
assertEquals(id(8), r.getObjectId());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
r = rc.getRef();
|
r = rc.getRef();
|
||||||
assertEquals("refs/heads/next", r.getName());
|
assertEquals("refs/heads/next", r.getName());
|
||||||
assertEquals(NEW, r.getStorage());
|
assertEquals(NEW, r.getStorage());
|
||||||
assertNull(r.getObjectId());
|
assertNull(r.getObjectId());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -277,6 +288,7 @@ public void oneTableSeek() throws IOException {
|
||||||
Ref act = rc.getRef();
|
Ref act = rc.getRef();
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
|
assertEquals(1, act.getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,17 +315,17 @@ public void missedUpdate() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/a", rc.getRef().getName());
|
assertEquals("refs/heads/a", rc.getRef().getName());
|
||||||
assertEquals(id(1), rc.getRef().getObjectId());
|
assertEquals(id(1), rc.getRef().getObjectId());
|
||||||
assertEquals(1, rc.getUpdateIndex());
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/b", rc.getRef().getName());
|
assertEquals("refs/heads/b", rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
assertEquals(2, rc.getUpdateIndex());
|
assertEquals(2, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals("refs/heads/c", rc.getRef().getName());
|
assertEquals("refs/heads/c", rc.getRef().getName());
|
||||||
assertEquals(id(3), rc.getRef().getObjectId());
|
assertEquals(id(3), rc.getRef().getObjectId());
|
||||||
assertEquals(3, rc.getUpdateIndex());
|
assertEquals(3, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +356,63 @@ public void compaction() throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void versioningSymbolicReftargetMoves() throws IOException {
|
||||||
|
Ref master = ref(MASTER, 100);
|
||||||
|
|
||||||
|
List<Ref> delta1 = Arrays.asList(master, sym(HEAD, MASTER));
|
||||||
|
List<Ref> delta2 = Arrays.asList(ref(MASTER, 200));
|
||||||
|
|
||||||
|
MergedReftable mr = merge(write(delta1, 1), write(delta2, 2));
|
||||||
|
Ref head = mr.exactRef(HEAD);
|
||||||
|
assertEquals(head.getUpdateIndex(), 1);
|
||||||
|
|
||||||
|
Ref masterRef = mr.exactRef(MASTER);
|
||||||
|
assertEquals(masterRef.getUpdateIndex(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void versioningSymbolicRefMoves() throws IOException {
|
||||||
|
Ref branchX = ref("refs/heads/branchX", 200);
|
||||||
|
|
||||||
|
List<Ref> delta1 = Arrays.asList(ref(MASTER, 100), branchX,
|
||||||
|
sym(HEAD, MASTER));
|
||||||
|
List<Ref> delta2 = Arrays.asList(sym(HEAD, "refs/heads/branchX"));
|
||||||
|
List<Ref> delta3 = Arrays.asList(sym(HEAD, MASTER));
|
||||||
|
|
||||||
|
MergedReftable mr = merge(write(delta1, 1), write(delta2, 2),
|
||||||
|
write(delta3, 3));
|
||||||
|
Ref head = mr.exactRef(HEAD);
|
||||||
|
assertEquals(head.getUpdateIndex(), 3);
|
||||||
|
|
||||||
|
Ref masterRef = mr.exactRef(MASTER);
|
||||||
|
assertEquals(masterRef.getUpdateIndex(), 1);
|
||||||
|
|
||||||
|
Ref branchRef = mr.exactRef(MASTER);
|
||||||
|
assertEquals(branchRef.getUpdateIndex(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void versioningResolveRef() throws IOException {
|
||||||
|
List<Ref> delta1 = Arrays.asList(sym(HEAD, "refs/heads/tmp"),
|
||||||
|
sym("refs/heads/tmp", MASTER), ref(MASTER, 100));
|
||||||
|
List<Ref> delta2 = Arrays.asList(ref(MASTER, 200));
|
||||||
|
List<Ref> delta3 = Arrays.asList(ref(MASTER, 300));
|
||||||
|
|
||||||
|
MergedReftable mr = merge(write(delta1, 1), write(delta2, 2),
|
||||||
|
write(delta3, 3));
|
||||||
|
Ref head = mr.exactRef(HEAD);
|
||||||
|
Ref resolvedHead = mr.resolve(head);
|
||||||
|
assertEquals(resolvedHead.getObjectId(), id(300));
|
||||||
|
assertEquals("HEAD has not moved", resolvedHead.getUpdateIndex(), 1);
|
||||||
|
|
||||||
|
Ref master = mr.exactRef(MASTER);
|
||||||
|
Ref resolvedMaster = mr.resolve(master);
|
||||||
|
assertEquals(resolvedMaster.getObjectId(), id(300));
|
||||||
|
assertEquals("master also has update index",
|
||||||
|
resolvedMaster.getUpdateIndex(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
private static MergedReftable merge(byte[]... table) {
|
private static MergedReftable merge(byte[]... table) {
|
||||||
List<Reftable> stack = new ArrayList<>(table.length);
|
List<Reftable> stack = new ArrayList<>(table.length);
|
||||||
for (byte[] b : table) {
|
for (byte[] b : table) {
|
||||||
|
@ -360,6 +429,14 @@ private static Ref ref(String name, int id) {
|
||||||
return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id));
|
return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Ref sym(String name, String target) {
|
||||||
|
return new SymbolicRef(name, newRef(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Ref newRef(String name) {
|
||||||
|
return new ObjectIdRef.Unpeeled(NEW, name, null);
|
||||||
|
}
|
||||||
|
|
||||||
private static Ref delete(String name) {
|
private static Ref delete(String name) {
|
||||||
return new ObjectIdRef.Unpeeled(NEW, name, null);
|
return new ObjectIdRef.Unpeeled(NEW, name, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ public void oneTable() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(MASTER, rc.getRef().getName());
|
assertEquals(MASTER, rc.getRef().getName());
|
||||||
assertEquals(id(1), rc.getRef().getObjectId());
|
assertEquals(id(1), rc.getRef().getObjectId());
|
||||||
assertEquals(0, rc.getUpdateIndex());
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ public void twoTablesOneRef() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(MASTER, rc.getRef().getName());
|
assertEquals(MASTER, rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
assertEquals(1, rc.getUpdateIndex());
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,12 +203,12 @@ public void twoTablesTwoRefs() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(MASTER, rc.getRef().getName());
|
assertEquals(MASTER, rc.getRef().getName());
|
||||||
assertEquals(id(3), rc.getRef().getObjectId());
|
assertEquals(id(3), rc.getRef().getObjectId());
|
||||||
assertEquals(1, rc.getUpdateIndex());
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(NEXT, rc.getRef().getName());
|
assertEquals(NEXT, rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
assertEquals(0, rc.getUpdateIndex());
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,7 @@ public void oneIdRef() throws IOException {
|
||||||
assertFalse(act.isSymbolic());
|
assertFalse(act.isSymbolic());
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
|
assertEquals(0, act.getUpdateIndex());
|
||||||
assertNull(act.getPeeledObjectId());
|
assertNull(act.getPeeledObjectId());
|
||||||
assertFalse(rc.wasDeleted());
|
assertFalse(rc.wasDeleted());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
|
@ -195,6 +196,7 @@ public void oneIdRef() throws IOException {
|
||||||
Ref act = rc.getRef();
|
Ref act = rc.getRef();
|
||||||
assertNotNull(act);
|
assertNotNull(act);
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
|
assertEquals(0, act.getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,6 +218,7 @@ public void oneTagRef() throws IOException {
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
assertEquals(exp.getPeeledObjectId(), act.getPeeledObjectId());
|
assertEquals(exp.getPeeledObjectId(), act.getPeeledObjectId());
|
||||||
|
assertEquals(0, act.getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +240,7 @@ public void oneSymbolicRef() throws IOException {
|
||||||
assertNotNull(act.getLeaf());
|
assertNotNull(act.getLeaf());
|
||||||
assertEquals(MASTER, act.getTarget().getName());
|
assertEquals(MASTER, act.getTarget().getName());
|
||||||
assertNull(act.getObjectId());
|
assertNull(act.getObjectId());
|
||||||
|
assertEquals(0, act.getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,14 +254,17 @@ public void resolveSymbolicRef() throws IOException {
|
||||||
Ref head = t.exactRef(HEAD);
|
Ref head = t.exactRef(HEAD);
|
||||||
assertNull(head.getObjectId());
|
assertNull(head.getObjectId());
|
||||||
assertEquals("refs/heads/tmp", head.getTarget().getName());
|
assertEquals("refs/heads/tmp", head.getTarget().getName());
|
||||||
|
assertEquals(0, head.getUpdateIndex());
|
||||||
|
|
||||||
head = t.resolve(head);
|
head = t.resolve(head);
|
||||||
assertNotNull(head);
|
assertNotNull(head);
|
||||||
assertEquals(id(1), head.getObjectId());
|
assertEquals(id(1), head.getObjectId());
|
||||||
|
assertEquals(0, head.getUpdateIndex());
|
||||||
|
|
||||||
Ref master = t.exactRef(MASTER);
|
Ref master = t.exactRef(MASTER);
|
||||||
assertNotNull(master);
|
assertNotNull(master);
|
||||||
assertSame(master, t.resolve(master));
|
assertSame(master, t.resolve(master));
|
||||||
|
assertEquals(0, master.getUpdateIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -335,14 +342,17 @@ public void namespaceHeads() throws IOException {
|
||||||
try (RefCursor rc = t.seekRefsWithPrefix("refs/tags/")) {
|
try (RefCursor rc = t.seekRefsWithPrefix("refs/tags/")) {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(V1_0, rc.getRef().getName());
|
assertEquals(V1_0, rc.getRef().getName());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
try (RefCursor rc = t.seekRefsWithPrefix("refs/heads/")) {
|
try (RefCursor rc = t.seekRefsWithPrefix("refs/heads/")) {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(MASTER, rc.getRef().getName());
|
assertEquals(MASTER, rc.getRef().getName());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(NEXT, rc.getRef().getName());
|
assertEquals(NEXT, rc.getRef().getName());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -432,11 +442,12 @@ public void withReflog() throws IOException {
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(MASTER, rc.getRef().getName());
|
assertEquals(MASTER, rc.getRef().getName());
|
||||||
assertEquals(id(1), rc.getRef().getObjectId());
|
assertEquals(id(1), rc.getRef().getObjectId());
|
||||||
assertEquals(1, rc.getUpdateIndex());
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertTrue(rc.next());
|
assertTrue(rc.next());
|
||||||
assertEquals(NEXT, rc.getRef().getName());
|
assertEquals(NEXT, rc.getRef().getName());
|
||||||
assertEquals(id(2), rc.getRef().getObjectId());
|
assertEquals(id(2), rc.getRef().getObjectId());
|
||||||
|
assertEquals(1, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
try (LogCursor lc = t.allLogs()) {
|
try (LogCursor lc = t.allLogs()) {
|
||||||
|
@ -569,6 +580,7 @@ public void byObjectIdOneRefNoIndex() throws IOException {
|
||||||
assertTrue("has 42", rc.next());
|
assertTrue("has 42", rc.next());
|
||||||
assertEquals("refs/heads/42", rc.getRef().getName());
|
assertEquals("refs/heads/42", rc.getRef().getName());
|
||||||
assertEquals(id(42), rc.getRef().getObjectId());
|
assertEquals(id(42), rc.getRef().getObjectId());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
try (RefCursor rc = t.byObjectId(id(100))) {
|
try (RefCursor rc = t.byObjectId(id(100))) {
|
||||||
|
@ -579,6 +591,7 @@ public void byObjectIdOneRefNoIndex() throws IOException {
|
||||||
assertTrue("has master", rc.next());
|
assertTrue("has master", rc.next());
|
||||||
assertEquals("refs/heads/master", rc.getRef().getName());
|
assertEquals("refs/heads/master", rc.getRef().getName());
|
||||||
assertEquals(id(100), rc.getRef().getObjectId());
|
assertEquals(id(100), rc.getRef().getObjectId());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -600,6 +613,7 @@ public void byObjectIdOneRefWithIndex() throws IOException {
|
||||||
assertTrue("has 42", rc.next());
|
assertTrue("has 42", rc.next());
|
||||||
assertEquals("refs/heads/42", rc.getRef().getName());
|
assertEquals("refs/heads/42", rc.getRef().getName());
|
||||||
assertEquals(id(42), rc.getRef().getObjectId());
|
assertEquals(id(42), rc.getRef().getObjectId());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
try (RefCursor rc = t.byObjectId(id(100))) {
|
try (RefCursor rc = t.byObjectId(id(100))) {
|
||||||
|
@ -610,6 +624,7 @@ public void byObjectIdOneRefWithIndex() throws IOException {
|
||||||
assertTrue("has master", rc.next());
|
assertTrue("has master", rc.next());
|
||||||
assertEquals("refs/heads/master", rc.getRef().getName());
|
assertEquals("refs/heads/master", rc.getRef().getName());
|
||||||
assertEquals(id(100), rc.getRef().getObjectId());
|
assertEquals(id(100), rc.getRef().getObjectId());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
|
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -654,7 +669,6 @@ public void badCrc32() throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void assertScan(List<Ref> refs, Reftable t)
|
private static void assertScan(List<Ref> refs, Reftable t)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try (RefCursor rc = t.allRefs()) {
|
try (RefCursor rc = t.allRefs()) {
|
||||||
|
@ -663,6 +677,7 @@ private static void assertScan(List<Ref> refs, Reftable t)
|
||||||
Ref act = rc.getRef();
|
Ref act = rc.getRef();
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
|
@ -676,6 +691,7 @@ private static void assertSeek(List<Ref> refs, Reftable t)
|
||||||
Ref act = rc.getRef();
|
Ref act = rc.getRef();
|
||||||
assertEquals(exp.getName(), act.getName());
|
assertEquals(exp.getName(), act.getName());
|
||||||
assertEquals(exp.getObjectId(), act.getObjectId());
|
assertEquals(exp.getObjectId(), act.getObjectId());
|
||||||
|
assertEquals(0, rc.getRef().getUpdateIndex());
|
||||||
assertFalse(rc.next());
|
assertFalse(rc.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,10 @@
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -114,11 +118,44 @@ public void testConstructor_Peeled() {
|
||||||
assertSame(ID_B, r.getPeeledObjectId());
|
assertSame(ID_B, r.getPeeledObjectId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateIndex() {
|
||||||
|
ObjectIdRef r;
|
||||||
|
|
||||||
|
r = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A, 3);
|
||||||
|
assertTrue(r.getUpdateIndex() == 3);
|
||||||
|
|
||||||
|
r = new ObjectIdRef.PeeledTag(Ref.Storage.LOOSE, name, ID_A, ID_B, 4);
|
||||||
|
assertTrue(r.getUpdateIndex() == 4);
|
||||||
|
|
||||||
|
r = new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, name, ID_A, 5);
|
||||||
|
assertTrue(r.getUpdateIndex() == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateIndexNotSet() {
|
||||||
|
List<ObjectIdRef> r = Arrays.asList(
|
||||||
|
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A),
|
||||||
|
new ObjectIdRef.PeeledTag(Ref.Storage.LOOSE, name, ID_A, ID_B),
|
||||||
|
new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, name, ID_A));
|
||||||
|
|
||||||
|
for (ObjectIdRef ref : r) {
|
||||||
|
try {
|
||||||
|
ref.getUpdateIndex();
|
||||||
|
fail("Update index wasn't set. It must throw");
|
||||||
|
} catch (UnsupportedOperationException u) {
|
||||||
|
// Ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToString() {
|
public void testToString() {
|
||||||
ObjectIdRef r;
|
ObjectIdRef r;
|
||||||
|
|
||||||
r = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A);
|
r = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A);
|
||||||
assertEquals("Ref[" + name + "=" + ID_A.name() + "]", r.toString());
|
assertEquals("Ref[" + name + "=" + ID_A.name() + "(-1)]",
|
||||||
|
r.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ public void testConstructor() {
|
||||||
SymbolicRef r;
|
SymbolicRef r;
|
||||||
|
|
||||||
t = new ObjectIdRef.Unpeeled(Ref.Storage.NEW, targetName, null);
|
t = new ObjectIdRef.Unpeeled(Ref.Storage.NEW, targetName, null);
|
||||||
r = new SymbolicRef(name, t);
|
r = new SymbolicRef(name, t, 1);
|
||||||
assertSame(Ref.Storage.LOOSE, r.getStorage());
|
assertSame(Ref.Storage.LOOSE, r.getStorage());
|
||||||
assertSame(name, r.getName());
|
assertSame(name, r.getName());
|
||||||
assertNull("no id on new ref", r.getObjectId());
|
assertNull("no id on new ref", r.getObjectId());
|
||||||
|
@ -77,9 +77,10 @@ public void testConstructor() {
|
||||||
assertSame("leaf is t", t, r.getLeaf());
|
assertSame("leaf is t", t, r.getLeaf());
|
||||||
assertSame("target is t", t, r.getTarget());
|
assertSame("target is t", t, r.getTarget());
|
||||||
assertTrue("is symbolic", r.isSymbolic());
|
assertTrue("is symbolic", r.isSymbolic());
|
||||||
|
assertTrue("holds update index", r.getUpdateIndex() == 1);
|
||||||
|
|
||||||
t = new ObjectIdRef.Unpeeled(Ref.Storage.PACKED, targetName, ID_A);
|
t = new ObjectIdRef.Unpeeled(Ref.Storage.PACKED, targetName, ID_A);
|
||||||
r = new SymbolicRef(name, t);
|
r = new SymbolicRef(name, t, 2);
|
||||||
assertSame(Ref.Storage.LOOSE, r.getStorage());
|
assertSame(Ref.Storage.LOOSE, r.getStorage());
|
||||||
assertSame(name, r.getName());
|
assertSame(name, r.getName());
|
||||||
assertSame(ID_A, r.getObjectId());
|
assertSame(ID_A, r.getObjectId());
|
||||||
|
@ -88,6 +89,7 @@ public void testConstructor() {
|
||||||
assertSame("leaf is t", t, r.getLeaf());
|
assertSame("leaf is t", t, r.getLeaf());
|
||||||
assertSame("target is t", t, r.getTarget());
|
assertSame("target is t", t, r.getTarget());
|
||||||
assertTrue("is symbolic", r.isSymbolic());
|
assertTrue("is symbolic", r.isSymbolic());
|
||||||
|
assertTrue("holds update index", r.getUpdateIndex() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -133,6 +135,6 @@ public void testToString() {
|
||||||
d = new SymbolicRef("D", c);
|
d = new SymbolicRef("D", c);
|
||||||
|
|
||||||
assertEquals("SymbolicRef[D -> C -> B -> " + targetName + "="
|
assertEquals("SymbolicRef[D -> C -> B -> " + targetName + "="
|
||||||
+ ID_A.name() + "]", d.toString());
|
+ ID_A.name() + "(-1)]", d.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,12 @@ protected DfsReftableDatabase(DfsRepository repo) {
|
||||||
super(repo);
|
super(repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public boolean hasVersioning() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public boolean performsAtomicTransactions() {
|
public boolean performsAtomicTransactions() {
|
||||||
|
|
|
@ -170,24 +170,27 @@ long readUpdateIndexDelta() {
|
||||||
return readVarint64();
|
return readVarint64();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref readRef() throws IOException {
|
Ref readRef(long minUpdateIndex) throws IOException {
|
||||||
|
long updateIndex = minUpdateIndex + readUpdateIndexDelta();
|
||||||
String name = RawParseUtils.decode(UTF_8, nameBuf, 0, nameLen);
|
String name = RawParseUtils.decode(UTF_8, nameBuf, 0, nameLen);
|
||||||
switch (valueType & VALUE_TYPE_MASK) {
|
switch (valueType & VALUE_TYPE_MASK) {
|
||||||
case VALUE_NONE: // delete
|
case VALUE_NONE: // delete
|
||||||
return newRef(name);
|
return newRef(name, updateIndex);
|
||||||
|
|
||||||
case VALUE_1ID:
|
case VALUE_1ID:
|
||||||
return new ObjectIdRef.PeeledNonTag(PACKED, name, readValueId());
|
return new ObjectIdRef.PeeledNonTag(PACKED, name, readValueId(),
|
||||||
|
updateIndex);
|
||||||
|
|
||||||
case VALUE_2ID: { // annotated tag
|
case VALUE_2ID: { // annotated tag
|
||||||
ObjectId id1 = readValueId();
|
ObjectId id1 = readValueId();
|
||||||
ObjectId id2 = readValueId();
|
ObjectId id2 = readValueId();
|
||||||
return new ObjectIdRef.PeeledTag(PACKED, name, id1, id2);
|
return new ObjectIdRef.PeeledTag(PACKED, name, id1, id2,
|
||||||
|
updateIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
case VALUE_SYMREF: {
|
case VALUE_SYMREF: {
|
||||||
String val = readValueString();
|
String val = readValueString();
|
||||||
return new SymbolicRef(name, newRef(val));
|
return new SymbolicRef(name, newRef(val, updateIndex), updateIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -410,7 +413,7 @@ void verifyIndex() throws IOException {
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #name()}
|
* <li>{@link #name()}
|
||||||
* <li>{@link #match(byte[], boolean)}
|
* <li>{@link #match(byte[], boolean)}
|
||||||
* <li>{@link #readRef()}
|
* <li>{@link #readRef(long)}
|
||||||
* <li>{@link #readLogUpdateIndex()}
|
* <li>{@link #readLogUpdateIndex()}
|
||||||
* <li>{@link #readLogEntry()}
|
* <li>{@link #readLogEntry()}
|
||||||
* <li>{@link #readBlockPositionList()}
|
* <li>{@link #readBlockPositionList()}
|
||||||
|
@ -575,8 +578,8 @@ private long readVarint64() {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ref newRef(String name) {
|
private static Ref newRef(String name, long updateIndex) {
|
||||||
return new ObjectIdRef.Unpeeled(NEW, name, null);
|
return new ObjectIdRef.Unpeeled(NEW, name, null, updateIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOException invalidBlock() {
|
private static IOException invalidBlock() {
|
||||||
|
|
|
@ -168,7 +168,6 @@ private class MergedRefCursor extends RefCursor {
|
||||||
private final PriorityQueue<RefQueueEntry> queue;
|
private final PriorityQueue<RefQueueEntry> queue;
|
||||||
private RefQueueEntry head;
|
private RefQueueEntry head;
|
||||||
private Ref ref;
|
private Ref ref;
|
||||||
private long updateIndex;
|
|
||||||
|
|
||||||
MergedRefCursor() {
|
MergedRefCursor() {
|
||||||
queue = new PriorityQueue<>(queueSize(), RefQueueEntry::compare);
|
queue = new PriorityQueue<>(queueSize(), RefQueueEntry::compare);
|
||||||
|
@ -206,7 +205,6 @@ public boolean next() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
ref = t.rc.getRef();
|
ref = t.rc.getRef();
|
||||||
updateIndex = t.rc.getUpdateIndex();
|
|
||||||
boolean include = includeDeletes || !t.rc.wasDeleted();
|
boolean include = includeDeletes || !t.rc.wasDeleted();
|
||||||
add(t);
|
add(t);
|
||||||
skipShadowedRefs(ref.getName());
|
skipShadowedRefs(ref.getName());
|
||||||
|
@ -241,11 +239,6 @@ public Ref getRef() {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUpdateIndex() {
|
|
||||||
return updateIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
if (head != null) {
|
if (head != null) {
|
||||||
|
@ -285,7 +278,7 @@ String name() {
|
||||||
}
|
}
|
||||||
|
|
||||||
long updateIndex() {
|
long updateIndex() {
|
||||||
return rc.getUpdateIndex();
|
return rc.getRef().getUpdateIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,13 +68,6 @@ public abstract class RefCursor implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public abstract Ref getRef();
|
public abstract Ref getRef();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get updateIndex that last modified the current reference.
|
|
||||||
*
|
|
||||||
* @return updateIndex that last modified the current reference.
|
|
||||||
*/
|
|
||||||
public abstract long getUpdateIndex();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the current reference was deleted.
|
* Whether the current reference was deleted.
|
||||||
*
|
*
|
||||||
|
|
|
@ -280,7 +280,7 @@ private Ref resolve(Ref ref, int depth) throws IOException {
|
||||||
if (dst == null) {
|
if (dst == null) {
|
||||||
return null; // claim it doesn't exist
|
return null; // claim it doesn't exist
|
||||||
}
|
}
|
||||||
return new SymbolicRef(ref.getName(), dst);
|
return new SymbolicRef(ref.getName(), dst, ref.getUpdateIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
|
|
|
@ -256,7 +256,7 @@ public Stats getStats() {
|
||||||
private void mergeRefs(MergedReftable mr) throws IOException {
|
private void mergeRefs(MergedReftable mr) throws IOException {
|
||||||
try (RefCursor rc = mr.allRefs()) {
|
try (RefCursor rc = mr.allRefs()) {
|
||||||
while (rc.next()) {
|
while (rc.next()) {
|
||||||
writer.writeRef(rc.getRef(), rc.getUpdateIndex());
|
writer.writeRef(rc.getRef(), rc.getRef().getUpdateIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,7 +479,6 @@ private class RefCursorImpl extends RefCursor {
|
||||||
private final boolean prefix;
|
private final boolean prefix;
|
||||||
|
|
||||||
private Ref ref;
|
private Ref ref;
|
||||||
private long updateIndex;
|
|
||||||
BlockReader block;
|
BlockReader block;
|
||||||
|
|
||||||
RefCursorImpl(long scanEnd, byte[] match, boolean prefix) {
|
RefCursorImpl(long scanEnd, byte[] match, boolean prefix) {
|
||||||
|
@ -508,8 +507,7 @@ public boolean next() throws IOException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateIndex = minUpdateIndex + block.readUpdateIndexDelta();
|
ref = block.readRef(minUpdateIndex);
|
||||||
ref = block.readRef();
|
|
||||||
if (!includeDeletes && wasDeleted()) {
|
if (!includeDeletes && wasDeleted()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -522,11 +520,6 @@ public Ref getRef() {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUpdateIndex() {
|
|
||||||
return updateIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -605,7 +598,6 @@ private class ObjCursorImpl extends RefCursor {
|
||||||
private final ObjectId match;
|
private final ObjectId match;
|
||||||
|
|
||||||
private Ref ref;
|
private Ref ref;
|
||||||
private long updateIndex;
|
|
||||||
private int listIdx;
|
private int listIdx;
|
||||||
|
|
||||||
private LongList blockPos;
|
private LongList blockPos;
|
||||||
|
@ -679,8 +671,7 @@ public boolean next() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
block.parseKey();
|
block.parseKey();
|
||||||
updateIndex = minUpdateIndex + block.readUpdateIndexDelta();
|
ref = block.readRef(minUpdateIndex);
|
||||||
ref = block.readRef();
|
|
||||||
ObjectId id = ref.getObjectId();
|
ObjectId id = ref.getObjectId();
|
||||||
if (id != null && match.equals(id)
|
if (id != null && match.equals(id)
|
||||||
&& (includeDeletes || !wasDeleted())) {
|
&& (includeDeletes || !wasDeleted())) {
|
||||||
|
@ -694,11 +685,6 @@ public Ref getRef() {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUpdateIndex() {
|
|
||||||
return updateIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
|
|
@ -67,7 +67,25 @@ public static class Unpeeled extends ObjectIdRef {
|
||||||
*/
|
*/
|
||||||
public Unpeeled(@NonNull Storage st, @NonNull String name,
|
public Unpeeled(@NonNull Storage st, @NonNull String name,
|
||||||
@Nullable ObjectId id) {
|
@Nullable ObjectId id) {
|
||||||
super(st, name, id);
|
super(st, name, id, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ref pairing with update index.
|
||||||
|
*
|
||||||
|
* @param st
|
||||||
|
* method used to store this ref.
|
||||||
|
* @param name
|
||||||
|
* name of this ref.
|
||||||
|
* @param id
|
||||||
|
* current value of the ref. May be {@code null} to indicate
|
||||||
|
* a ref that does not exist yet.
|
||||||
|
* @param updateIndex
|
||||||
|
* number increasing with each update to the reference.
|
||||||
|
*/
|
||||||
|
public Unpeeled(@NonNull Storage st, @NonNull String name,
|
||||||
|
@Nullable ObjectId id, long updateIndex) {
|
||||||
|
super(st, name, id, updateIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,7 +118,28 @@ public static class PeeledTag extends ObjectIdRef {
|
||||||
*/
|
*/
|
||||||
public PeeledTag(@NonNull Storage st, @NonNull String name,
|
public PeeledTag(@NonNull Storage st, @NonNull String name,
|
||||||
@Nullable ObjectId id, @NonNull ObjectId p) {
|
@Nullable ObjectId id, @NonNull ObjectId p) {
|
||||||
super(st, name, id);
|
super(st, name, id, -1);
|
||||||
|
peeledObjectId = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ref pairing with update index.
|
||||||
|
*
|
||||||
|
* @param st
|
||||||
|
* method used to store this ref.
|
||||||
|
* @param name
|
||||||
|
* name of this ref.
|
||||||
|
* @param id
|
||||||
|
* current value of the ref. May be {@code null} to indicate
|
||||||
|
* a ref that does not exist yet.
|
||||||
|
* @param p
|
||||||
|
* the first non-tag object that tag {@code id} points to.
|
||||||
|
* @param updateIndex
|
||||||
|
* number increasing with each update to the reference.
|
||||||
|
*/
|
||||||
|
public PeeledTag(@NonNull Storage st, @NonNull String name,
|
||||||
|
@Nullable ObjectId id, @NonNull ObjectId p, long updateIndex) {
|
||||||
|
super(st, name, id, updateIndex);
|
||||||
peeledObjectId = p;
|
peeledObjectId = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +170,25 @@ public static class PeeledNonTag extends ObjectIdRef {
|
||||||
*/
|
*/
|
||||||
public PeeledNonTag(@NonNull Storage st, @NonNull String name,
|
public PeeledNonTag(@NonNull Storage st, @NonNull String name,
|
||||||
@Nullable ObjectId id) {
|
@Nullable ObjectId id) {
|
||||||
super(st, name, id);
|
super(st, name, id, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ref pairing with update index.
|
||||||
|
*
|
||||||
|
* @param st
|
||||||
|
* method used to store this ref.
|
||||||
|
* @param name
|
||||||
|
* name of this ref.
|
||||||
|
* @param id
|
||||||
|
* current value of the ref. May be {@code null} to indicate
|
||||||
|
* a ref that does not exist yet.
|
||||||
|
* @param updateIndex
|
||||||
|
* number increasing with each update to the reference.
|
||||||
|
*/
|
||||||
|
public PeeledNonTag(@NonNull Storage st, @NonNull String name,
|
||||||
|
@Nullable ObjectId id, long updateIndex) {
|
||||||
|
super(st, name, id, updateIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -152,6 +209,8 @@ public boolean isPeeled() {
|
||||||
|
|
||||||
private final ObjectId objectId;
|
private final ObjectId objectId;
|
||||||
|
|
||||||
|
private final long updateIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new ref pairing.
|
* Create a new ref pairing.
|
||||||
*
|
*
|
||||||
|
@ -162,12 +221,16 @@ public boolean isPeeled() {
|
||||||
* @param id
|
* @param id
|
||||||
* current value of the ref. May be {@code null} to indicate a
|
* current value of the ref. May be {@code null} to indicate a
|
||||||
* ref that does not exist yet.
|
* ref that does not exist yet.
|
||||||
|
* @param updateIndex
|
||||||
|
* number that increases with each ref update. Set to -1 if the
|
||||||
|
* storage doesn't support versioning.
|
||||||
*/
|
*/
|
||||||
protected ObjectIdRef(@NonNull Storage st, @NonNull String name,
|
protected ObjectIdRef(@NonNull Storage st, @NonNull String name,
|
||||||
@Nullable ObjectId id) {
|
@Nullable ObjectId id, long updateIndex) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.storage = st;
|
this.storage = st;
|
||||||
this.objectId = id;
|
this.objectId = id;
|
||||||
|
this.updateIndex = updateIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
|
@ -211,6 +274,15 @@ public Storage getStorage() {
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public long getUpdateIndex() {
|
||||||
|
if (updateIndex == -1) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
return updateIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
|
@ -220,7 +292,9 @@ public String toString() {
|
||||||
r.append(getName());
|
r.append(getName());
|
||||||
r.append('=');
|
r.append('=');
|
||||||
r.append(ObjectId.toString(getObjectId()));
|
r.append(ObjectId.toString(getObjectId()));
|
||||||
r.append(']');
|
r.append('(');
|
||||||
|
r.append(updateIndex); // Print value, even if -1
|
||||||
|
r.append(")]"); //$NON-NLS-1$
|
||||||
return r.toString();
|
return r.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,4 +217,27 @@ public boolean isPacked() {
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
Storage getStorage();
|
Storage getStorage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicator of the relative order between updates of a specific reference
|
||||||
|
* name. A number that increases when a reference is updated.
|
||||||
|
* <p>
|
||||||
|
* With symbolic references, the update index refers to updates of the
|
||||||
|
* symbolic reference itself. For example, if HEAD points to
|
||||||
|
* refs/heads/master, then the update index for exactRef("HEAD") will only
|
||||||
|
* increase when HEAD changes to point to another ref, regardless of how
|
||||||
|
* many times refs/heads/master is updated.
|
||||||
|
* <p>
|
||||||
|
* Should not be used unless the {@code RefDatabase} that instantiated the
|
||||||
|
* ref supports versioning (see {@link RefDatabase#hasVersioning()})
|
||||||
|
*
|
||||||
|
* @return the update index (i.e. version) of this reference.
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
* if the creator of the instance (e.g. {@link RefDatabase})
|
||||||
|
* doesn't support versioning and doesn't override this method
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
default long getUpdateIndex() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,19 @@ public abstract class RefDatabase {
|
||||||
*/
|
*/
|
||||||
public abstract void close();
|
public abstract void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* With versioning, each reference has a version number that increases on
|
||||||
|
* update. See {@link Ref#getUpdateIndex()}.
|
||||||
|
*
|
||||||
|
* @implSpec This method returns false by default. Implementations
|
||||||
|
* supporting versioning must override it to return true.
|
||||||
|
* @return true if the implementation assigns update indices to references.
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public boolean hasVersioning() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a proposed reference name overlaps with an existing one.
|
* Determine if a proposed reference name overlaps with an existing one.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
|
@ -58,6 +58,8 @@ public class SymbolicRef implements Ref {
|
||||||
|
|
||||||
private final Ref target;
|
private final Ref target;
|
||||||
|
|
||||||
|
private final long updateIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new ref pairing.
|
* Create a new ref pairing.
|
||||||
*
|
*
|
||||||
|
@ -69,6 +71,24 @@ public class SymbolicRef implements Ref {
|
||||||
public SymbolicRef(@NonNull String refName, @NonNull Ref target) {
|
public SymbolicRef(@NonNull String refName, @NonNull Ref target) {
|
||||||
this.name = refName;
|
this.name = refName;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
this.updateIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ref pairing.
|
||||||
|
*
|
||||||
|
* @param refName
|
||||||
|
* name of this ref.
|
||||||
|
* @param target
|
||||||
|
* the ref we reference and derive our value from.
|
||||||
|
* @param updateIndex
|
||||||
|
* index that increases with each update of the reference
|
||||||
|
*/
|
||||||
|
public SymbolicRef(@NonNull String refName, @NonNull Ref target,
|
||||||
|
long updateIndex) {
|
||||||
|
this.name = refName;
|
||||||
|
this.target = target;
|
||||||
|
this.updateIndex = updateIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
|
@ -128,6 +148,15 @@ public boolean isPeeled() {
|
||||||
return getLeaf().isPeeled();
|
return getLeaf().isPeeled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public long getUpdateIndex() {
|
||||||
|
if (updateIndex == -1) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
return updateIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
@Override
|
@Override
|
||||||
|
@ -143,7 +172,9 @@ public String toString() {
|
||||||
r.append(cur.getName());
|
r.append(cur.getName());
|
||||||
r.append('=');
|
r.append('=');
|
||||||
r.append(ObjectId.toString(cur.getObjectId()));
|
r.append(ObjectId.toString(cur.getObjectId()));
|
||||||
r.append("]");
|
r.append("(");
|
||||||
|
r.append(updateIndex); // Print value, even if -1
|
||||||
|
r.append(")]");
|
||||||
return r.toString();
|
return r.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue