changeset 28204:962921c330b0

verify: check for orphaned dirlogs We already report orphaned filelogs, i.e. revlogs for files that are not mentioned in any manifest. This change adds checking for orphaned dirlogs, i.e. revlogs that are not mentioned in any parent-directory dirlog. Note that, for fncachestore, only files mentioned in the fncache are considered, there's not check for files in .hg/store/meta that are not mentioned in the fncache. This is no different from the current situation for filelogs.
author Martin von Zweigbergk <martinvonz@google.com>
date Wed, 03 Feb 2016 15:35:15 -0800
parents 7297e9e13a8a
children 53f42c8d5f71
files mercurial/verify.py tests/test-treemanifest.t
diffstat 2 files changed, 24 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/verify.py	Sun Feb 07 21:13:24 2016 -0800
+++ b/mercurial/verify.py	Wed Feb 03 15:35:15 2016 -0800
@@ -197,7 +197,7 @@
         ui.progress(_('checking'), None)
         return mflinkrevs, filelinkrevs
 
-    def _verifymanifest(self, mflinkrevs, dir=""):
+    def _verifymanifest(self, mflinkrevs, dir="", storefiles=None):
         repo = self.repo
         ui = self.ui
         mf = self.repo.manifest.dirlog(dir)
@@ -211,6 +211,8 @@
         label = "manifest"
         if dir:
             label = dir
+            revlogfiles = mf.files()
+            storefiles.difference_update(revlogfiles)
         if self.refersmf:
             # Do not check manifest if there are only changelog entries with
             # null manifests.
@@ -260,11 +262,23 @@
 
         if not dir and subdirnodes:
             self.ui.status(_("checking directory manifests\n"))
+            storefiles = set()
+            revlogv1 = self.revlogv1
+            for f, f2, size in repo.store.datafiles():
+                if not f:
+                    self.err(None, _("cannot decode filename '%s'") % f2)
+                elif (size > 0 or not revlogv1) and f.startswith('meta/'):
+                    storefiles.add(_normpath(f))
+
         for subdir, linkrevs in subdirnodes.iteritems():
-            subdirfilenodes = self._verifymanifest(linkrevs, subdir)
+            subdirfilenodes = self._verifymanifest(linkrevs, subdir, storefiles)
             for f, onefilenodes in subdirfilenodes.iteritems():
                 filenodes.setdefault(f, {}).update(onefilenodes)
 
+        if not dir and subdirnodes:
+            for f in sorted(storefiles):
+                self.warn(_("warning: orphan revlog '%s'") % f)
+
         return filenodes
 
     def _crosscheckfiles(self, filelinkrevs, filenodes):
@@ -402,7 +416,7 @@
                              short(node), f)
         ui.progress(_('checking'), None)
 
-        for f in storefiles:
+        for f in sorted(storefiles):
             self.warn(_("warning: orphan revlog '%s'") % f)
 
         return len(files), revisions
--- a/tests/test-treemanifest.t	Sun Feb 07 21:13:24 2016 -0800
+++ b/tests/test-treemanifest.t	Wed Feb 03 15:35:15 2016 -0800
@@ -517,6 +517,12 @@
    b/@0: parent-directory manifest refers to unknown revision 67688a370455
    b/@1: parent-directory manifest refers to unknown revision f38e85d334c5
    b/@2: parent-directory manifest refers to unknown revision 99c9792fd4b0
+  warning: orphan revlog 'meta/b/bar/00manifest.i'
+  warning: orphan revlog 'meta/b/bar/orange/00manifest.i'
+  warning: orphan revlog 'meta/b/bar/orange/fly/00manifest.i'
+  warning: orphan revlog 'meta/b/foo/00manifest.i'
+  warning: orphan revlog 'meta/b/foo/apple/00manifest.i'
+  warning: orphan revlog 'meta/b/foo/apple/bees/00manifest.i'
   crosschecking files in changesets and manifests
    b/bar/fruits.txt@0: in changeset but not in manifest
    b/bar/orange/fly/gnat.py@0: in changeset but not in manifest
@@ -524,6 +530,7 @@
    b/foo/apple/bees/flower.py@0: in changeset but not in manifest
   checking files
   8 files, 3 changesets, 10 total revisions
+  6 warnings encountered!
   8 integrity errors encountered!
   (first damaged changeset appears to be 0)
   [1]