reftable: pass on invalid object ID in conversion

Before, while trying to determine if an object ID was a tag or not,
the reftable conversion would yield an exception.

Change-Id: I3688a0ffa9e774ba27f320e3840ff8cada21ecf0
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 2ffbc62..4907073 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
@@ -58,7 +58,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.List;
@@ -162,20 +164,21 @@ public void testConvert() throws Exception {
 		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/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
index c0dc625..e5ffd77 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
@@ -59,6 +59,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;
@@ -615,15 +616,20 @@ private static Ref refForWrite(RevWalk rw, Ref r) throws IOException {
 					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);
 	}