Merge branch 'stable-5.13'

* stable-5.13:
  Fix missing peel-part in lsRefsV2 for loose annotated tags
  Fix RevWalk.getMergedInto() ignores annotated tags
  Optimize RevWalk.getMergedInto()
  reftable: drop code for truncated reads
  reftable: pass on invalid object ID in conversion
  Update eclipse-jarsigner-plugin to 1.3.2
  Fix running benchmarks from bazel
  Update eclipse-jarsigner-plugin to 1.3.2
  Add org.bouncycastle.bcutil to p2 repository

Change-Id: I789e3c84045cc9dcd8a26de34d09fc1e3ccc41e7
diff --git a/org.eclipse.jgit.benchmarks/BUILD b/org.eclipse.jgit.benchmarks/BUILD
index 7e331b1..ecd268c 100644
--- a/org.eclipse.jgit.benchmarks/BUILD
+++ b/org.eclipse.jgit.benchmarks/BUILD
@@ -8,6 +8,8 @@
     name = "benchmarks",
     srcs = SRCS,
     deps = [
+        "//lib:javaewah",
+        "//lib:slf4j-api",
         "//org.eclipse.jgit:jgit",
     ],
 )
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
index a56cf0a..ca0935a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
@@ -147,6 +147,12 @@
    <bundle id="org.bouncycastle.bcprov.source">
       <category name="JGit-dependency-bundles"/>
    </bundle>
+   <bundle id="org.bouncycastle.bcutil">
+      <category name="JGit-dependency-bundles"/>
+   </bundle>
+   <bundle id="org.bouncycastle.bcutil.source">
+      <category name="JGit-dependency-bundles"/>
+   </bundle>
    <bundle id="org.kohsuke.args4j">
       <category name="JGit-dependency-bundles"/>
    </bundle>
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java
index 15c9109..32342e3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java
@@ -25,7 +25,9 @@
 import static org.junit.Assert.fail;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -133,20 +135,21 @@
 		assertTrue(db.getRefDatabase().hasFastTipsWithSha1());
 	}
 
+
 	@Test
-	public void testConvertToRefdir() throws Exception {
+	public void testConvertBrokenObjectId() throws Exception {
 		db.convertToPackedRefs(false, false);
-		assertTrue(db.getRefDatabase() instanceof RefDirectory);
-		Ref h = db.exactRef("HEAD");
-		assertTrue(h.isSymbolic());
-		assertEquals("refs/heads/master", h.getTarget().getName());
+		new File(db.getDirectory(), "refs/heads").mkdirs();
 
-		Ref b = db.exactRef("refs/heads/b");
-		assertFalse(b.isSymbolic());
-		assertTrue(b.isPeeled());
-		assertEquals(bCommit, b.getObjectId().name());
+		String invalidId = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
+		File headFile = new File(db.getDirectory(), "refs/heads/broken");
+		try (OutputStream os = new FileOutputStream(headFile)) {
+			os.write(Constants.encodeASCII(invalidId + "\n"));
+		}
 
-		assertFalse(db.getRefDatabase().hasFastTipsWithSha1());
+		Ref r = db.exactRef("refs/heads/broken");
+		assertNotNull(r);
+		db.convertToReftable(true, false);
 	}
 
 	@Test
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 0d739b9..ea0d92a 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
@@ -941,6 +941,12 @@
 			}
 			assertFalse(lc.next());
 		}
+
+		for (Ref exp : refs) {
+ 			try (LogCursor lc = t.seekLog(exp.getName())) {
+				assertTrue("has " + exp.getName(), lc.next());
+			}
+		}
 	}
 
 	@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java
index 2f16aa4..2754bd3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java
@@ -99,7 +99,7 @@
 		createBranch(commit(commit(a)), b);
 		createBranch(commit(commit(i)), c);
 
-		assertTrue( rw.isMergedIntoAny(a, getRefs()));
+		assertTrue(rw.isMergedIntoAny(a, getRefs()));
 	}
 
 	@Test
@@ -125,4 +125,23 @@
 
 		assertTrue(rw.isMergedIntoAll(a, getRefs()));
 	}
+
+	@Test
+	public void testMergeIntoAnnotatedTag() throws Exception {
+		/*
+		 *        a
+		 *        |
+		 *        b
+		 *       / \
+		 *      c  v1 (annotated tag)
+		 */
+		String c = "refs/heads/c";
+		String v1 = "refs/tags/v1";
+		final RevCommit a = commit();
+		final RevCommit b = commit(a);
+		createBranch(commit(b), c);
+		createBranch(tag("v1", b), v1);
+
+		assertTrue(rw.isMergedIntoAll(a, getRefs()));
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
index 200cb6a..0a045c9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
@@ -82,20 +82,33 @@
 		 *  a   b
 		 *  |   |
 		 *  c   d
+		 *      | \
+		 *      f  e
+		 *      | /
+		 *      g
 		 */
 		RevCommit a = commit();
 		RevCommit b = commit();
 		RevCommit c = commit(a);
 		RevCommit d = commit(b);
+		RevCommit f = commit(d);
+		RevCommit e = commit(d);
+		RevCommit g = commit(f, e);
 		Ref branchA = branch("a", a);
 		Ref branchB = branch("b", b);
 		Ref branchC = branch("c", c);
 		Ref branchD = branch("d", d);
+		Ref branchE = branch("e", e);
+		Ref branchF = branch("f", f);
+		Ref branchG = branch("g", g);
 
 		assertContains(a, asList(branchA, branchC));
-		assertContains(b, asList(branchB, branchD));
+		assertContains(b, asList(branchB, branchD, branchE, branchF, branchG));
 		assertContains(c, asList(branchC));
-		assertContains(d, asList(branchD));
+		assertContains(d, asList(branchD, branchE, branchF, branchG));
+		assertContains(e, asList(branchE, branchG));
+		assertContains(f, asList(branchF, branchG));
+		assertContains(g, asList(branchG));
 	}
 
 	private Ref branch(String name, RevCommit dst) throws Exception {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackLsRefsFileRepositoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackLsRefsFileRepositoryTest.java
new file mode 100644
index 0000000..7d5fc61
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackLsRefsFileRepositoryTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021, Saša Živkov <sasa.zivkov@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.transport;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Sets;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTag;
+import org.junit.Before;
+import org.junit.Test;
+
+// TODO: refactor UploadPackTest to run against both DfsRepository and FileRepository
+public class UploadPackLsRefsFileRepositoryTest
+		extends LocalDiskRepositoryTestCase {
+
+	private FileRepository server;
+
+	private TestRepository<FileRepository> remote;
+
+	@Before
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		server = createWorkRepository();
+		remote = new TestRepository<>(server);
+	}
+
+	@Test
+	public void testV2LsRefsPeel() throws Exception {
+		RevCommit tip = remote.commit().message("message").create();
+		remote.update("master", tip);
+		server.updateRef("HEAD").link("refs/heads/master");
+		RevTag tag = remote.tag("tag", tip);
+		remote.update("refs/tags/tag", tag);
+
+		ByteArrayInputStream recvStream = uploadPackV2("command=ls-refs\n",
+				PacketLineIn.delimiter(), "peel", PacketLineIn.end());
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		assertThat(pckIn.readString(),
+				is(tip.toObjectId().getName() + " HEAD"));
+		assertThat(pckIn.readString(),
+				is(tip.toObjectId().getName() + " refs/heads/master"));
+		assertThat(pckIn.readString(), is(tag.toObjectId().getName()
+				+ " refs/tags/tag peeled:" + tip.toObjectId().getName()));
+		assertTrue(PacketLineIn.isEnd(pckIn.readString()));
+	}
+
+	private ByteArrayInputStream uploadPackV2(String... inputLines)
+			throws Exception {
+		return uploadPackV2(null, inputLines);
+	}
+
+	private ByteArrayInputStream uploadPackV2(
+			Consumer<UploadPack> postConstructionSetup, String... inputLines)
+			throws Exception {
+		ByteArrayInputStream recvStream = uploadPackV2Setup(
+				postConstructionSetup, inputLines);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		// drain capabilities
+		while (!PacketLineIn.isEnd(pckIn.readString())) {
+			// do nothing
+		}
+		return recvStream;
+	}
+
+	private ByteArrayInputStream uploadPackV2Setup(
+			Consumer<UploadPack> postConstructionSetup, String... inputLines)
+			throws Exception {
+
+		ByteArrayInputStream send = linesAsInputStream(inputLines);
+
+		server.getConfig().setString("protocol", null, "version", "2");
+		UploadPack up = new UploadPack(server);
+		if (postConstructionSetup != null) {
+			postConstructionSetup.accept(up);
+		}
+		up.setExtraParameters(Sets.of("version=2"));
+
+		ByteArrayOutputStream recv = new ByteArrayOutputStream();
+		up.upload(send, recv, null);
+
+		return new ByteArrayInputStream(recv.toByteArray());
+	}
+
+	private static ByteArrayInputStream linesAsInputStream(String... inputLines)
+			throws IOException {
+		try (ByteArrayOutputStream send = new ByteArrayOutputStream()) {
+			PacketLineOut pckOut = new PacketLineOut(send);
+			for (String line : inputLines) {
+				Objects.requireNonNull(line);
+				if (PacketLineIn.isEnd(line)) {
+					pckOut.end();
+				} else if (PacketLineIn.isDelimiter(line)) {
+					pckOut.writeDelim();
+				} else {
+					pckOut.writeString(line);
+				}
+			}
+			return new ByteArrayInputStream(send.toByteArray());
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
index a80fa837..e9e17c0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
@@ -28,6 +28,7 @@
 import java.util.stream.Collectors;
 
 import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.events.RefsChangedEvent;
 import org.eclipse.jgit.internal.storage.reftable.MergedReftable;
 import org.eclipse.jgit.internal.storage.reftable.ReftableBatchRefUpdate;
@@ -592,15 +593,20 @@
 					r.getTarget().getName(), null));
 		}
 		ObjectId newId = r.getObjectId();
-		RevObject obj = rw.parseAny(newId);
 		RevObject peel = null;
-		if (obj instanceof RevTag) {
-			peel = rw.peel(obj);
+		try {
+			RevObject obj = rw.parseAny(newId);
+			if (obj instanceof RevTag) {
+				peel = rw.peel(obj);
+			}
+		} catch (MissingObjectException e) {
+			/* ignore this error and copy the dangling object ID into reftable too. */
 		}
 		if (peel != null) {
-			return new ObjectIdRef.PeeledTag(PACKED, r.getName(), newId,
-					peel.copy());
-		}
+				return new ObjectIdRef.PeeledTag(PACKED, r.getName(), newId,
+						peel.copy());
+			}
+
 		return new ObjectIdRef.PeeledNonTag(PACKED, r.getName(), newId);
 	}
 
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 0096312..d07713d 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
@@ -59,7 +59,6 @@
 class BlockReader {
 	private byte blockType;
 	private long endPosition;
-	private boolean truncated;
 
 	private byte[] buf;
 	private int bufLen;
@@ -79,10 +78,6 @@
 		return blockType;
 	}
 
-	boolean truncated() {
-		return truncated;
-	}
-
 	long endPosition() {
 		return endPosition;
 	}
@@ -298,16 +293,8 @@
 			// Log blocks must be inflated after the header.
 			long deflatedSize = inflateBuf(src, pos, blockLen, fileBlockSize);
 			endPosition = pos + 4 + deflatedSize;
-		}
-		if (bufLen < blockLen) {
-			if (blockType != INDEX_BLOCK_TYPE) {
-				throw invalidBlock();
-			}
-			// Its OK during sequential scan for an index block to have been
-			// partially read and be truncated in-memory. This happens when
-			// the index block is larger than the file's blockSize. Caller
-			// will break out of its scan loop once it sees the blockType.
-			truncated = true;
+		} else if (bufLen < blockLen) {
+			readBlockIntoBuf(src, pos, blockLen);
 		} else if (bufLen > blockLen) {
 			bufLen = blockLen;
 		}
@@ -372,7 +359,7 @@
 	}
 
 	void verifyIndex() throws IOException {
-		if (blockType != INDEX_BLOCK_TYPE || truncated) {
+		if (blockType != INDEX_BLOCK_TYPE) {
 			throw invalidBlock();
 		}
 	}
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 9e2ae91..cabb2e1 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
@@ -435,7 +435,7 @@
 
 		BlockReader b = new BlockReader();
 		b.readBlock(src, pos, sz);
-		if (b.type() == INDEX_BLOCK_TYPE && !b.truncated()) {
+		if (b.type() == INDEX_BLOCK_TYPE) {
 			if (indexCache == null) {
 				indexCache = new LongMap<>();
 			}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
index c06ca0b..8d571f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -528,6 +528,7 @@
 				Enum returnStrategy, ProgressMonitor monitor) throws IOException {
 		List<Ref> result = new ArrayList<>();
 		List<RevCommit> uninteresting = new ArrayList<>();
+		List<RevCommit> marked = new ArrayList<>();
 		RevFilter oldRF = filter;
 		TreeFilter oldTF = treeFilter;
 		try {
@@ -540,22 +541,25 @@
 					return result;
 				}
 				monitor.update(1);
-				RevObject o = parseAny(r.getObjectId());
+				RevObject o = peel(parseAny(r.getObjectId()));
 				if (!(o instanceof RevCommit)) {
 					continue;
 				}
 				RevCommit c = (RevCommit) o;
-				resetRetain(RevFlag.UNINTERESTING);
+				reset(UNINTERESTING | TEMP_MARK);
 				markStart(c);
 				boolean commitFound = false;
 				RevCommit next;
 				while ((next = next()) != null) {
-					if (References.isSameObject(next, needle)) {
+					if (References.isSameObject(next, needle)
+							|| (next.flags & TEMP_MARK) != 0) {
 						result.add(r);
 						if (returnStrategy == GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND) {
 							return result;
 						}
 						commitFound = true;
+						c.flags |= TEMP_MARK;
+						marked.add(c);
 						break;
 					}
 				}
@@ -571,6 +575,9 @@
 			roots.addAll(uninteresting);
 			filter = oldRF;
 			treeFilter = oldTF;
+			for (RevCommit c : marked) {
+				c.flags &= ~TEMP_MARK;
+			}
 		}
 		return result;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index 258271d..fa24480 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -1092,6 +1092,7 @@
 
 		rawOut.stopBuffering();
 		PacketLineOutRefAdvertiser adv = new PacketLineOutRefAdvertiser(pckOut);
+		adv.init(db);
 		adv.setUseProtocolV2(true);
 		if (req.getPeel()) {
 			adv.setDerefTags(true);
diff --git a/pom.xml b/pom.xml
index 6d98b7c..0833c71 100644
--- a/pom.xml
+++ b/pom.xml
@@ -827,8 +827,8 @@
               </compilerArgs>
               <annotationProcessorPaths>
                 <path>
-                <groupId>com.google.errorprone</groupId>
-                <artifactId>error_prone_core</artifactId>
+                  <groupId>com.google.errorprone</groupId>
+                  <artifactId>error_prone_core</artifactId>
                   <version>2.9.0</version>
                 </path>
               </annotationProcessorPaths>