D4701: verify: start to abstract file verification
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Wed Sep 26 13:23:10 EDT 2018
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG97986c9c69d3: verify: start to abstract file verification (authored by indygreg, committed by ).
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D4701?vs=11309&id=11373
REVISION DETAIL
https://phab.mercurial-scm.org/D4701
AFFECTED FILES
mercurial/filelog.py
mercurial/repository.py
mercurial/revlog.py
mercurial/verify.py
tests/test-check-interfaces.py
CHANGE DETAILS
diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py
--- a/tests/test-check-interfaces.py
+++ b/tests/test-check-interfaces.py
@@ -229,4 +229,8 @@
basenode=b'')
checkzobject(rdr)
+ ziverify.verifyClass(repository.iverifyproblem,
+ revlog.revlogproblem)
+ checkzobject(revlog.revlogproblem())
+
main()
diff --git a/mercurial/verify.py b/mercurial/verify.py
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -341,6 +341,10 @@
elif (size > 0 or not revlogv1) and f.startswith('data/'):
storefiles.add(_normpath(f))
+ state = {
+ 'revlogv1': self.revlogv1,
+ }
+
files = sorted(set(filenodes) | set(filelinkrevs))
revisions = 0
progress = ui.makeprogress(_('checking'), unit=_('files'),
@@ -373,7 +377,19 @@
ff)
self.fncachewarned = True
- self.checklog(fl, f, lr)
+ if not len(fl) and (self.havecl or self.havemf):
+ self.err(lr, _("empty or missing %s") % f)
+ else:
+ for problem in fl.verifyintegrity(state):
+ if problem.warning:
+ self.warn(problem.warning)
+ elif problem.error:
+ self.err(lr, problem.error, f)
+ else:
+ raise error.ProgrammingError(
+ 'problem instance does not set warning or error '
+ 'attribute: %s' % problem.msg)
+
seen = {}
rp = None
for i in fl:
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -254,6 +254,12 @@
revision = attr.ib()
delta = attr.ib()
+ at interfaceutil.implementer(repository.iverifyproblem)
+ at attr.s(frozen=True)
+class revlogproblem(object):
+ warning = attr.ib(default=None)
+ error = attr.ib(default=None)
+
# index v0:
# 4 bytes: offset
# 4 bytes: compressed length
@@ -2581,3 +2587,23 @@
if dataread is not idxread:
dataread.close()
datawrite.close()
+
+ def verifyintegrity(self, state):
+ """Verifies the integrity of the revlog.
+
+ Yields ``revlogproblem`` instances describing problems that are
+ found.
+ """
+ dd, di = self.checksize()
+ if dd:
+ yield revlogproblem(error=_('data length off by %d bytes') % dd)
+ if di:
+ yield revlogproblem(error=_('index contains %d extra bytes') % di)
+
+ if self.version != REVLOGV0:
+ if not state['revlogv1']:
+ yield revlogproblem(warning=_("warning: `%s' uses revlog "
+ "format 1") % self.indexfile)
+ elif state['revlogv1']:
+ yield revlogproblem(warning=_("warning: `%s' uses revlog "
+ "format 0") % self.indexfile)
diff --git a/mercurial/repository.py b/mercurial/repository.py
--- a/mercurial/repository.py
+++ b/mercurial/repository.py
@@ -318,6 +318,20 @@
_('cannot %s; remote repository does not support the %r '
'capability') % (purpose, name))
+class iverifyproblem(interfaceutil.Interface):
+ """Represents a problem with the integrity of the repository.
+
+ Instances of this interface are emitted to describe an integrity issue
+ with a repository (e.g. corrupt storage, missing data, etc).
+
+ Instances are essentially messages associated with severity.
+ """
+ warning = interfaceutil.Attribute(
+ """Message indicating a non-fatal problem.""")
+
+ error = interfaceutil.Attribute(
+ """Message indicating a fatal problem.""")
+
class irevisiondelta(interfaceutil.Interface):
"""Represents a delta between one revision and another.
@@ -749,6 +763,17 @@
TODO this is used by verify and it should not be part of the interface.
"""
+ def verifyintegrity(state):
+ """Verifies the integrity of file storage.
+
+ ``state`` is a dict holding state of the verifier process. It can be
+ used to communicate data between invocations of multiple storage
+ primitives.
+
+ The method yields objects conforming to the ``iverifyproblem``
+ interface.
+ """
+
class idirs(interfaceutil.Interface):
"""Interface representing a collection of directories from paths.
diff --git a/mercurial/filelog.py b/mercurial/filelog.py
--- a/mercurial/filelog.py
+++ b/mercurial/filelog.py
@@ -189,6 +189,9 @@
return True
+ def verifyintegrity(self, state):
+ return self._revlog.verifyintegrity(state)
+
# TODO these aren't part of the interface and aren't internal methods.
# Callers should be fixed to not use them.
To: indygreg, #hg-reviewers
Cc: mharbison72, mercurial-devel
More information about the Mercurial-devel
mailing list