From 673acfc6bdff0e339e47a7f950a44580fa74a637 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Fri, 14 Jul 2017 11:42:34 -0700 Subject: [PATCH] Add connectivity check from references Make sure all objects referenced by references are reachable. Stop at the first missing object. Change-Id: Ifcd7392c4321b17d9290bd87f038bc62bc10dabb Signed-off-by: Zhen Chen --- .../internal/storage/dfs/DfsFsckTest.java | 42 +++++++++++++++++++ .../jgit/internal/storage/dfs/DfsFsck.java | 16 +++++++ 2 files changed, 58 insertions(+) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsFsckTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsFsckTest.java index 3fa3952454..8d223c80d9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsFsckTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsFsckTest.java @@ -198,4 +198,46 @@ public class DfsFsckTest { } } } + + @Test + public void testValidConnectivity() throws Exception { + ObjectId blobId = ins + .insert(Constants.OBJ_BLOB, Constants.encode("foo")); + + byte[] blobIdBytes = new byte[OBJECT_ID_LENGTH]; + blobId.copyRawTo(blobIdBytes, 0); + byte[] data = concat(encodeASCII("100644 regular-file\0"), blobIdBytes); + ObjectId treeId = ins.insert(Constants.OBJ_TREE, data); + ins.flush(); + + RevCommit commit = git.commit().message("0").setTopLevelTree(treeId) + .create(); + + git.update("master", commit); + + DfsFsck fsck = new DfsFsck(repo); + FsckError errors = fsck.check(null); + assertEquals(errors.getMissingObjects().size(), 0); + } + + @Test + public void testMissingObject() throws Exception { + ObjectId blobId = ObjectId + .fromString("19102815663d23f8b75a47e7a01965dcdc96468c"); + byte[] blobIdBytes = new byte[OBJECT_ID_LENGTH]; + blobId.copyRawTo(blobIdBytes, 0); + byte[] data = concat(encodeASCII("100644 regular-file\0"), blobIdBytes); + ObjectId treeId = ins.insert(Constants.OBJ_TREE, data); + ins.flush(); + + RevCommit commit = git.commit().message("0").setTopLevelTree(treeId) + .create(); + + git.update("master", commit); + + DfsFsck fsck = new DfsFsck(repo); + FsckError errors = fsck.check(null); + assertEquals(errors.getMissingObjects().size(), 1); + assertEquals(errors.getMissingObjects().iterator().next(), blobId); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java index 1cc475a9fe..9549dbb2ea 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java @@ -54,6 +54,9 @@ import org.eclipse.jgit.internal.fsck.FsckPackParser; import org.eclipse.jgit.internal.storage.pack.PackExt; import org.eclipse.jgit.lib.ObjectChecker; import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.revwalk.ObjectWalk; +import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.transport.PackedObjectInfo; /** Verify the validity and connectivity of a DFS repository. */ @@ -115,6 +118,19 @@ public class DfsFsck { e.getErrorType())); } } + + try (ObjectWalk ow = new ObjectWalk(ctx)) { + for (Ref r : repo.getAllRefs().values()) { + try { + RevObject tip = ow.parseAny(r.getObjectId()); + ow.markStart(tip); + ow.checkConnectivity(); + ow.markUninteresting(tip); + } catch (MissingObjectException e) { + errors.getMissingObjects().add(e.getObjectId()); + } + } + } } finally { ctx.close(); } -- 2.39.5