]> source.dussan.org Git - jgit.git/commitdiff
reftable: add ReftableReflogReader 65/147565/20
authorHan-Wen Nienhuys <hanwen@google.com>
Mon, 12 Aug 2019 17:04:07 +0000 (19:04 +0200)
committerHan-Wen Nienhuys <hanwen@google.com>
Wed, 11 Sep 2019 10:59:55 +0000 (12:59 +0200)
Change-Id: Iac2c4ac5e3aad0fa37157ed8866f1987d80268d6
Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReflogReader.java [new file with mode: 0644]

index 0e33fa6e76bbb54518b4c669da833b1d5ed223c8..bd87147479e58af659763f34f0570195b8b08a66 100644 (file)
@@ -66,6 +66,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
 
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.io.BlockSource;
@@ -76,6 +78,7 @@ import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.ReflogEntry;
 import org.eclipse.jgit.lib.SymbolicRef;
+import org.hamcrest.Matchers;
 import org.junit.Test;
 
 public class ReftableTest {
@@ -522,6 +525,47 @@ public class ReftableTest {
                }
        }
 
+       @Test
+       public void reflogReader() throws IOException {
+               Ref master = ref(MASTER, 1);
+               Ref next = ref(NEXT, 2);
+
+               ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+               ReftableWriter writer = new ReftableWriter().setMinUpdateIndex(1)
+                               .setMaxUpdateIndex(1).begin(buffer);
+
+               writer.writeRef(master);
+               writer.writeRef(next);
+
+               PersonIdent who1 = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+               writer.writeLog(MASTER, 3, who1, ObjectId.zeroId(), id(1), "1");
+               PersonIdent who2 = new PersonIdent("Log", "Ger", 1500079710, -8 * 60);
+               writer.writeLog(MASTER, 2, who2, id(1), id(2), "2");
+               PersonIdent who3 = new PersonIdent("Log", "Ger", 1500079711, -8 * 60);
+               writer.writeLog(MASTER, 1, who3, id(2), id(3), "3");
+
+               writer.finish();
+               byte[] table = buffer.toByteArray();
+
+               ReentrantLock lock = new ReentrantLock();
+               ReftableReader t = read(table);
+               ReftableReflogReader rlr = new ReftableReflogReader(lock, t, MASTER);
+
+               assertEquals(rlr.getLastEntry().getWho(), who1);
+               List<PersonIdent> all = rlr.getReverseEntries().stream()
+                               .map(x -> x.getWho()).collect(Collectors.toList());
+               Matchers.contains(all, who3, who2, who1);
+
+               assertEquals(rlr.getReverseEntry(1).getWho(), who2);
+
+               List<ReflogEntry> reverse2 = rlr.getReverseEntries(2);
+               Matchers.contains(reverse2, who3, who2);
+
+               List<PersonIdent> more = rlr.getReverseEntries(4).stream()
+                               .map(x -> x.getWho()).collect(Collectors.toList());
+               assertEquals(all, more);
+       }
+
        @Test
        public void reflogSeek() throws IOException {
                PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReflogReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReflogReader.java
new file mode 100644 (file)
index 0000000..c75d3cf
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019, Google LLC
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.reftable;
+
+import org.eclipse.jgit.lib.ReflogEntry;
+import org.eclipse.jgit.lib.ReflogReader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * Implement the ReflogReader interface for a reflog stored in reftable.
+ */
+public class ReftableReflogReader implements ReflogReader {
+       private final Lock lock;
+
+       private final Reftable reftable;
+
+       private final String refname;
+
+       ReftableReflogReader(Lock lock, Reftable merged, String refname) {
+               this.lock = lock;
+               this.reftable = merged;
+               this.refname = refname;
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public ReflogEntry getLastEntry() throws IOException {
+               lock.lock();
+               try {
+                       LogCursor cursor = reftable.seekLog(refname);
+                       return cursor.next() ? cursor.getReflogEntry() : null;
+               } finally {
+                       lock.unlock();
+               }
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public List<ReflogEntry> getReverseEntries() throws IOException {
+               return getReverseEntries(Integer.MAX_VALUE);
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public ReflogEntry getReverseEntry(int number) throws IOException {
+               lock.lock();
+               try {
+                       LogCursor cursor = reftable.seekLog(refname);
+                       while (true) {
+                               if (!cursor.next() || number < 0) {
+                                       return null;
+                               }
+                               if (number == 0) {
+                                       return cursor.getReflogEntry();
+                               }
+                               number--;
+                       }
+               } finally {
+                       lock.unlock();
+               }
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public List<ReflogEntry> getReverseEntries(int max) throws IOException {
+               lock.lock();
+               try {
+                       LogCursor cursor = reftable.seekLog(refname);
+
+                       List<ReflogEntry> result = new ArrayList<>();
+                       while (cursor.next() && result.size() < max) {
+                               result.add(cursor.getReflogEntry());
+                       }
+
+                       return result;
+               } finally {
+                       lock.unlock();
+               }
+       }
+}