aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java28
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java83
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java8
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java20
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java39
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java19
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java84
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java23
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java33
17 files changed, 342 insertions, 60 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
index 5a2bd9c333..56346e1d85 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
@@ -61,6 +61,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -134,6 +135,33 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase {
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
public void testGetRefs_EmptyDatabase() throws IOException {
Map<String, Ref> all;
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 1d11573b99..11d6439931 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
@@ -44,6 +44,7 @@
package org.eclipse.jgit.internal.storage.reftable;
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.R_HEADS;
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
@@ -68,6 +69,7 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
+import org.eclipse.jgit.lib.SymbolicRef;
import org.junit.Test;
public class MergedReftableTest {
@@ -128,6 +130,7 @@ public class MergedReftableTest {
Ref act = rc.getRef();
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
+ assertEquals(1, act.getUpdateIndex());
}
assertFalse(rc.next());
}
@@ -145,6 +148,7 @@ public class MergedReftableTest {
assertTrue(rc.next());
assertEquals("refs/heads/master", rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
}
@@ -162,6 +166,7 @@ public class MergedReftableTest {
assertEquals("refs/heads/master", rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
assertFalse(rc.next());
+ assertEquals(1, rc.getRef().getUpdateIndex());
}
}
@@ -177,6 +182,7 @@ public class MergedReftableTest {
assertTrue(rc.next());
assertEquals("refs/heads/master", rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
}
@@ -212,6 +218,7 @@ public class MergedReftableTest {
Ref act = rc.getRef();
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
+ assertEquals(1, rc.getRef().getUpdateIndex());
}
assertFalse(rc.next());
}
@@ -231,9 +238,11 @@ public class MergedReftableTest {
assertTrue(rc.next());
assertEquals("refs/heads/apple", rc.getRef().getName());
assertEquals(id(3), rc.getRef().getObjectId());
+ assertEquals(2000, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
assertEquals("refs/heads/banana", rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
+ assertEquals(1000, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
}
@@ -251,12 +260,14 @@ public class MergedReftableTest {
Ref r = rc.getRef();
assertEquals("refs/heads/master", r.getName());
assertEquals(id(8), r.getObjectId());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
r = rc.getRef();
assertEquals("refs/heads/next", r.getName());
assertEquals(NEW, r.getStorage());
assertNull(r.getObjectId());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
@@ -277,6 +288,7 @@ public class MergedReftableTest {
Ref act = rc.getRef();
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
+ assertEquals(1, act.getUpdateIndex());
assertFalse(rc.next());
}
}
@@ -303,17 +315,17 @@ public class MergedReftableTest {
assertTrue(rc.next());
assertEquals("refs/heads/a", rc.getRef().getName());
assertEquals(id(1), rc.getRef().getObjectId());
- assertEquals(1, rc.getUpdateIndex());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
assertEquals("refs/heads/b", rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
- assertEquals(2, rc.getUpdateIndex());
+ assertEquals(2, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
assertEquals("refs/heads/c", rc.getRef().getName());
assertEquals(id(3), rc.getRef().getObjectId());
- assertEquals(3, rc.getUpdateIndex());
+ assertEquals(3, rc.getRef().getUpdateIndex());
}
}
@@ -344,6 +356,63 @@ public class MergedReftableTest {
}
}
+ @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) {
List<Reftable> stack = new ArrayList<>(table.length);
for (byte[] b : table) {
@@ -360,6 +429,14 @@ public class MergedReftableTest {
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) {
return new ObjectIdRef.Unpeeled(NEW, name, null);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java
index 46a37ff603..1ea73097fe 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java
@@ -108,7 +108,7 @@ public class ReftableCompactorTest {
assertTrue(rc.next());
assertEquals(MASTER, rc.getRef().getName());
assertEquals(id(1), rc.getRef().getObjectId());
- assertEquals(0, rc.getUpdateIndex());
+ assertEquals(0, rc.getRef().getUpdateIndex());
}
}
@@ -155,7 +155,7 @@ public class ReftableCompactorTest {
assertTrue(rc.next());
assertEquals(MASTER, rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
- assertEquals(1, rc.getUpdateIndex());
+ assertEquals(1, rc.getRef().getUpdateIndex());
}
}
@@ -203,12 +203,12 @@ public class ReftableCompactorTest {
assertTrue(rc.next());
assertEquals(MASTER, rc.getRef().getName());
assertEquals(id(3), rc.getRef().getObjectId());
- assertEquals(1, rc.getUpdateIndex());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
assertEquals(NEXT, rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
- assertEquals(0, rc.getUpdateIndex());
+ assertEquals(0, rc.getRef().getUpdateIndex());
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
index 0ee785c60c..a142166983 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
@@ -186,6 +186,7 @@ public class ReftableTest {
assertFalse(act.isSymbolic());
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
+ assertEquals(0, act.getUpdateIndex());
assertNull(act.getPeeledObjectId());
assertFalse(rc.wasDeleted());
assertFalse(rc.next());
@@ -195,6 +196,7 @@ public class ReftableTest {
Ref act = rc.getRef();
assertNotNull(act);
assertEquals(exp.getName(), act.getName());
+ assertEquals(0, act.getUpdateIndex());
assertFalse(rc.next());
}
}
@@ -216,6 +218,7 @@ public class ReftableTest {
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
assertEquals(exp.getPeeledObjectId(), act.getPeeledObjectId());
+ assertEquals(0, act.getUpdateIndex());
}
}
@@ -237,6 +240,7 @@ public class ReftableTest {
assertNotNull(act.getLeaf());
assertEquals(MASTER, act.getTarget().getName());
assertNull(act.getObjectId());
+ assertEquals(0, act.getUpdateIndex());
}
}
@@ -250,14 +254,17 @@ public class ReftableTest {
Ref head = t.exactRef(HEAD);
assertNull(head.getObjectId());
assertEquals("refs/heads/tmp", head.getTarget().getName());
+ assertEquals(0, head.getUpdateIndex());
head = t.resolve(head);
assertNotNull(head);
assertEquals(id(1), head.getObjectId());
+ assertEquals(0, head.getUpdateIndex());
Ref master = t.exactRef(MASTER);
assertNotNull(master);
assertSame(master, t.resolve(master));
+ assertEquals(0, master.getUpdateIndex());
}
@Test
@@ -335,14 +342,17 @@ public class ReftableTest {
try (RefCursor rc = t.seekRefsWithPrefix("refs/tags/")) {
assertTrue(rc.next());
assertEquals(V1_0, rc.getRef().getName());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
try (RefCursor rc = t.seekRefsWithPrefix("refs/heads/")) {
assertTrue(rc.next());
assertEquals(MASTER, rc.getRef().getName());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
assertEquals(NEXT, rc.getRef().getName());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
@@ -432,11 +442,12 @@ public class ReftableTest {
assertTrue(rc.next());
assertEquals(MASTER, rc.getRef().getName());
assertEquals(id(1), rc.getRef().getObjectId());
- assertEquals(1, rc.getUpdateIndex());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertTrue(rc.next());
assertEquals(NEXT, rc.getRef().getName());
assertEquals(id(2), rc.getRef().getObjectId());
+ assertEquals(1, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
try (LogCursor lc = t.allLogs()) {
@@ -569,6 +580,7 @@ public class ReftableTest {
assertTrue("has 42", rc.next());
assertEquals("refs/heads/42", rc.getRef().getName());
assertEquals(id(42), rc.getRef().getObjectId());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
try (RefCursor rc = t.byObjectId(id(100))) {
@@ -579,6 +591,7 @@ public class ReftableTest {
assertTrue("has master", rc.next());
assertEquals("refs/heads/master", rc.getRef().getName());
assertEquals(id(100), rc.getRef().getObjectId());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
@@ -600,6 +613,7 @@ public class ReftableTest {
assertTrue("has 42", rc.next());
assertEquals("refs/heads/42", rc.getRef().getName());
assertEquals(id(42), rc.getRef().getObjectId());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
try (RefCursor rc = t.byObjectId(id(100))) {
@@ -610,6 +624,7 @@ public class ReftableTest {
assertTrue("has master", rc.next());
assertEquals("refs/heads/master", rc.getRef().getName());
assertEquals(id(100), rc.getRef().getObjectId());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
@@ -654,7 +669,6 @@ public class ReftableTest {
}
}
-
private static void assertScan(List<Ref> refs, Reftable t)
throws IOException {
try (RefCursor rc = t.allRefs()) {
@@ -663,6 +677,7 @@ public class ReftableTest {
Ref act = rc.getRef();
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
+ assertEquals(0, rc.getRef().getUpdateIndex());
}
assertFalse(rc.next());
}
@@ -676,6 +691,7 @@ public class ReftableTest {
Ref act = rc.getRef();
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getObjectId(), act.getObjectId());
+ assertEquals(0, rc.getRef().getUpdateIndex());
assertFalse(rc.next());
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java
index fb16c6baca..6553bfa830 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java
@@ -48,6 +48,10 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.List;
import org.junit.Test;
@@ -115,10 +119,43 @@ public class ObjectIdRefTest {
}
@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
public void testToString() {
ObjectIdRef r;
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());
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java
index 1342253c05..99b2211e69 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java
@@ -68,7 +68,7 @@ public class SymbolicRefTest {
SymbolicRef r;
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(name, r.getName());
assertNull("no id on new ref", r.getObjectId());
@@ -77,9 +77,10 @@ public class SymbolicRefTest {
assertSame("leaf is t", t, r.getLeaf());
assertSame("target is t", t, r.getTarget());
assertTrue("is symbolic", r.isSymbolic());
+ assertTrue("holds update index", r.getUpdateIndex() == 1);
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(name, r.getName());
assertSame(ID_A, r.getObjectId());
@@ -88,6 +89,7 @@ public class SymbolicRefTest {
assertSame("leaf is t", t, r.getLeaf());
assertSame("target is t", t, r.getTarget());
assertTrue("is symbolic", r.isSymbolic());
+ assertTrue("holds update index", r.getUpdateIndex() == 2);
}
@Test
@@ -133,6 +135,6 @@ public class SymbolicRefTest {
d = new SymbolicRef("D", c);
assertEquals("SymbolicRef[D -> C -> B -> " + targetName + "="
- + ID_A.name() + "]", d.toString());
+ + ID_A.name() + "(-1)]", d.toString());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
index 70816307f5..0e0a6ef5e4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
@@ -99,6 +99,12 @@ public class DfsReftableDatabase extends DfsRefDatabase {
/** {@inheritDoc} */
@Override
+ public boolean hasVersioning() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public boolean performsAtomicTransactions() {
return true;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
index ce2ba4a2e1..44529bfff2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
@@ -170,24 +170,27 @@ class BlockReader {
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);
switch (valueType & VALUE_TYPE_MASK) {
case VALUE_NONE: // delete
- return newRef(name);
+ return newRef(name, updateIndex);
case VALUE_1ID:
- return new ObjectIdRef.PeeledNonTag(PACKED, name, readValueId());
+ return new ObjectIdRef.PeeledNonTag(PACKED, name, readValueId(),
+ updateIndex);
case VALUE_2ID: { // annotated tag
ObjectId id1 = readValueId();
ObjectId id2 = readValueId();
- return new ObjectIdRef.PeeledTag(PACKED, name, id1, id2);
+ return new ObjectIdRef.PeeledTag(PACKED, name, id1, id2,
+ updateIndex);
}
case VALUE_SYMREF: {
String val = readValueString();
- return new SymbolicRef(name, newRef(val));
+ return new SymbolicRef(name, newRef(val, updateIndex), updateIndex);
}
default:
@@ -410,7 +413,7 @@ class BlockReader {
* <ul>
* <li>{@link #name()}
* <li>{@link #match(byte[], boolean)}
- * <li>{@link #readRef()}
+ * <li>{@link #readRef(long)}
* <li>{@link #readLogUpdateIndex()}
* <li>{@link #readLogEntry()}
* <li>{@link #readBlockPositionList()}
@@ -575,8 +578,8 @@ class BlockReader {
return val;
}
- private static Ref newRef(String name) {
- return new ObjectIdRef.Unpeeled(NEW, name, null);
+ private static Ref newRef(String name, long updateIndex) {
+ return new ObjectIdRef.Unpeeled(NEW, name, null, updateIndex);
}
private static IOException invalidBlock() {
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 17894b1664..c740bf2c37 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
@@ -168,7 +168,6 @@ public class MergedReftable extends Reftable {
private final PriorityQueue<RefQueueEntry> queue;
private RefQueueEntry head;
private Ref ref;
- private long updateIndex;
MergedRefCursor() {
queue = new PriorityQueue<>(queueSize(), RefQueueEntry::compare);
@@ -206,7 +205,6 @@ public class MergedReftable extends Reftable {
}
ref = t.rc.getRef();
- updateIndex = t.rc.getUpdateIndex();
boolean include = includeDeletes || !t.rc.wasDeleted();
add(t);
skipShadowedRefs(ref.getName());
@@ -242,11 +240,6 @@ public class MergedReftable extends Reftable {
}
@Override
- public long getUpdateIndex() {
- return updateIndex;
- }
-
- @Override
public void close() {
if (head != null) {
head.rc.close();
@@ -285,7 +278,7 @@ public class MergedReftable extends Reftable {
}
long updateIndex() {
- return rc.getUpdateIndex();
+ return rc.getRef().getUpdateIndex();
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java
index 5d4af30a91..9749ffb906 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java
@@ -69,13 +69,6 @@ public abstract class RefCursor implements AutoCloseable {
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.
*
* @return {@code true} if the current reference was deleted.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java
index a1087e2023..cb02628e8d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java
@@ -280,7 +280,7 @@ public abstract class Reftable implements AutoCloseable {
if (dst == null) {
return null; // claim it doesn't exist
}
- return new SymbolicRef(ref.getName(), dst);
+ return new SymbolicRef(ref.getName(), dst, ref.getUpdateIndex());
}
/** {@inheritDoc} */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java
index ed73a9efbd..c4e8f69fa4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java
@@ -256,7 +256,7 @@ public class ReftableCompactor {
private void mergeRefs(MergedReftable mr) throws IOException {
try (RefCursor rc = mr.allRefs()) {
while (rc.next()) {
- writer.writeRef(rc.getRef(), rc.getUpdateIndex());
+ writer.writeRef(rc.getRef(), rc.getRef().getUpdateIndex());
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
index 81b30e4cb9..bf3a9aeca0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
@@ -479,7 +479,6 @@ public class ReftableReader extends Reftable {
private final boolean prefix;
private Ref ref;
- private long updateIndex;
BlockReader block;
RefCursorImpl(long scanEnd, byte[] match, boolean prefix) {
@@ -508,8 +507,7 @@ public class ReftableReader extends Reftable {
return false;
}
- updateIndex = minUpdateIndex + block.readUpdateIndexDelta();
- ref = block.readRef();
+ ref = block.readRef(minUpdateIndex);
if (!includeDeletes && wasDeleted()) {
continue;
}
@@ -523,11 +521,6 @@ public class ReftableReader extends Reftable {
}
@Override
- public long getUpdateIndex() {
- return updateIndex;
- }
-
- @Override
public void close() {
// Do nothing.
}
@@ -605,7 +598,6 @@ public class ReftableReader extends Reftable {
private final ObjectId match;
private Ref ref;
- private long updateIndex;
private int listIdx;
private LongList blockPos;
@@ -679,8 +671,7 @@ public class ReftableReader extends Reftable {
}
block.parseKey();
- updateIndex = minUpdateIndex + block.readUpdateIndexDelta();
- ref = block.readRef();
+ ref = block.readRef(minUpdateIndex);
ObjectId id = ref.getObjectId();
if (id != null && match.equals(id)
&& (includeDeletes || !wasDeleted())) {
@@ -695,11 +686,6 @@ public class ReftableReader extends Reftable {
}
@Override
- public long getUpdateIndex() {
- return updateIndex;
- }
-
- @Override
public void close() {
// Do nothing.
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
index 22aaa3ad73..747318170a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
@@ -67,7 +67,25 @@ public abstract class ObjectIdRef implements Ref {
*/
public Unpeeled(@NonNull Storage st, @NonNull String name,
@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
@@ -100,7 +118,28 @@ public abstract class ObjectIdRef implements Ref {
*/
public PeeledTag(@NonNull Storage st, @NonNull String name,
@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;
}
@@ -131,7 +170,25 @@ public abstract class ObjectIdRef implements Ref {
*/
public PeeledNonTag(@NonNull Storage st, @NonNull String name,
@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
@@ -152,6 +209,8 @@ public abstract class ObjectIdRef implements Ref {
private final ObjectId objectId;
+ private final long updateIndex;
+
/**
* Create a new ref pairing.
*
@@ -162,12 +221,16 @@ public abstract class ObjectIdRef implements Ref {
* @param id
* current value of the ref. May be {@code null} to indicate a
* 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,
- @Nullable ObjectId id) {
+ @Nullable ObjectId id, long updateIndex) {
this.name = name;
this.storage = st;
this.objectId = id;
+ this.updateIndex = updateIndex;
}
/** {@inheritDoc} */
@@ -212,6 +275,15 @@ public abstract class ObjectIdRef implements Ref {
}
/** {@inheritDoc} */
+ @Override
+ public long getUpdateIndex() {
+ if (updateIndex == -1) {
+ throw new UnsupportedOperationException();
+ }
+ return updateIndex;
+ }
+
+ /** {@inheritDoc} */
@NonNull
@Override
public String toString() {
@@ -220,7 +292,9 @@ public abstract class ObjectIdRef implements Ref {
r.append(getName());
r.append('=');
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();
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
index faabbf892f..32c8b06c91 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
@@ -217,4 +217,27 @@ public interface Ref {
*/
@NonNull
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();
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
index 68929b4220..5010a89ed5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
@@ -111,6 +111,19 @@ public abstract class RefDatabase {
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.
* <p>
* Reference names use '/' as a component separator, and may be stored in a
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
index d4b83b0128..0e9a23fe15 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
@@ -58,6 +58,8 @@ public class SymbolicRef implements Ref {
private final Ref target;
+ private final long updateIndex;
+
/**
* Create a new ref pairing.
*
@@ -69,6 +71,24 @@ public class SymbolicRef implements Ref {
public SymbolicRef(@NonNull String refName, @NonNull Ref target) {
this.name = refName;
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} */
@@ -129,6 +149,15 @@ public class SymbolicRef implements Ref {
}
/** {@inheritDoc} */
+ @Override
+ public long getUpdateIndex() {
+ if (updateIndex == -1) {
+ throw new UnsupportedOperationException();
+ }
+ return updateIndex;
+ }
+
+ /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
@@ -143,7 +172,9 @@ public class SymbolicRef implements Ref {
r.append(cur.getName());
r.append('=');
r.append(ObjectId.toString(cur.getObjectId()));
- r.append("]");
+ r.append("(");
+ r.append(updateIndex); // Print value, even if -1
+ r.append(")]");
return r.toString();
}
}