##// END OF EJS Templates
setdiscovery: use progress helper...
setdiscovery: use progress helper Differential Revision: https://phab.mercurial-scm.org/D3770

File last commit:

r37435:76d2115c default
r38369:9e70690a default
Show More
verify.py
492 lines | 19.1 KiB | text/x-python | PythonLexer
Matt Mackall
Move repo.verify
r2778 # verify.py - repository integrity checking for Mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
Matt Mackall
Move repo.verify
r2778 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Move repo.verify
r2778
Gregory Szorc
verify: use absolute_import
r25991 from __future__ import absolute_import
Bryan O'Sullivan
verify: fix all doubled-slash sites (issue3665)
r17860 import os
Gregory Szorc
verify: use absolute_import
r25991
from .i18n import _
from .node import (
nullid,
short,
)
from . import (
error,
Pulkit Goyal
py3: use pycompat.bytestr() instead of str()...
r35603 pycompat,
Gregory Szorc
verify: use absolute_import
r25991 revlog,
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 scmutil,
Gregory Szorc
verify: use absolute_import
r25991 util,
)
Matt Mackall
Move repo.verify
r2778
def verify(repo):
Bryan O'Sullivan
with: use context manager in verify
r27849 with repo.lock():
Durham Goode
verify: move widely used variables into class members...
r27444 return verifier(repo).verify()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915
Bryan O'Sullivan
verify: fix all doubled-slash sites (issue3665)
r17860 def _normpath(f):
# under hg < 2.4, convert didn't sanitize paths properly, so a
# converted repo may contain repeated slashes
while '//' in f:
f = f.replace('//', '/')
return f
Durham Goode
verify: move verify logic into a class...
r27443 class verifier(object):
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 # The match argument is always None in hg core, but e.g. the narrowhg
# extension will pass in a matcher here.
def __init__(self, repo, match=None):
Durham Goode
verify: move widely used variables into class members...
r27444 self.repo = repo.unfiltered()
self.ui = repo.ui
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 self.match = match or scmutil.matchall(repo)
Durham Goode
verify: move widely used variables into class members...
r27444 self.badrevs = set()
Matt Mackall
verify: clean up weird error/warning lists...
r27453 self.errors = 0
self.warnings = 0
Durham Goode
verify: move widely used variables into class members...
r27444 self.havecl = len(repo.changelog) > 0
Durham Goode
manifest: remove last uses of repo.manifest...
r30375 self.havemf = len(repo.manifestlog._revlog) > 0
Durham Goode
verify: move widely used variables into class members...
r27444 self.revlogv1 = repo.changelog.version != revlog.REVLOGV0
Martin von Zweigbergk
verify: remove dependence on repo.changectx()...
r37318 self.lrugetctx = util.lrucachefunc(repo.__getitem__)
Durham Goode
verify: move widely used variables into class members...
r27444 self.refersmf = False
Durham Goode
verify: move fncachewarned up to a class variable...
r27445 self.fncachewarned = False
Jun Wu
verify: add a config option to skip certain flag processors...
r32288 # developer config: verify.skipflags
self.skipflags = repo.ui.configint('verify', 'skipflags')
Gregory Szorc
verify: allow suppressing warnings about extra files...
r37435 self.warnorphanstorefiles = True
Durham Goode
verify: move widely used variables into class members...
r27444
Durham Goode
verify: move warn() to a class level function...
r27446 def warn(self, msg):
self.ui.warn(msg + "\n")
Matt Mackall
verify: clean up weird error/warning lists...
r27453 self.warnings += 1
Durham Goode
verify: move warn() to a class level function...
r27446
Durham Goode
verify: move err() to be a class function...
r27447 def err(self, linkrev, msg, filename=None):
if linkrev is not None:
self.badrevs.add(linkrev)
Pulkit Goyal
py3: use "%d" to convert integers to bytes...
r36203 linkrev = "%d" % linkrev
Durham Goode
verify: move err() to be a class function...
r27447 else:
linkrev = '?'
msg = "%s: %s" % (linkrev, msg)
if filename:
msg = "%s@%s" % (filename, msg)
self.ui.warn(" " + msg + "\n")
Matt Mackall
verify: clean up weird error/warning lists...
r27453 self.errors += 1
Durham Goode
verify: move err() to be a class function...
r27447
Durham Goode
verify: move exc() function onto class...
r27448 def exc(self, linkrev, msg, inst, filename=None):
Augie Fackler
verify: fix exception formatting bug in Python 3...
r36595 fmsg = pycompat.bytestr(inst)
if not fmsg:
fmsg = pycompat.byterepr(inst)
self.err(linkrev, "%s: %s" % (msg, fmsg), filename)
Durham Goode
verify: move exc() function onto class...
r27448
Durham Goode
verify: move checklog() onto class...
r27642 def checklog(self, obj, name, linkrev):
if not len(obj) and (self.havecl or self.havemf):
self.err(linkrev, _("empty or missing %s") % name)
return
d = obj.checksize()
if d[0]:
self.err(None, _("data length off by %d bytes") % d[0], name)
if d[1]:
self.err(None, _("index contains %d extra bytes") % d[1], name)
if obj.version != revlog.REVLOGV0:
if not self.revlogv1:
self.warn(_("warning: `%s' uses revlog format 1") % name)
elif self.revlogv1:
self.warn(_("warning: `%s' uses revlog format 0") % name)
Durham Goode
verify: move checkentry() to be a class function...
r27643 def checkentry(self, obj, i, node, seen, linkrevs, f):
lr = obj.linkrev(obj.rev(node))
if lr < 0 or (self.havecl and lr not in linkrevs):
if lr < 0 or lr >= len(self.repo.changelog):
msg = _("rev %d points to nonexistent changeset %d")
else:
msg = _("rev %d points to unexpected changeset %d")
self.err(None, msg % (i, lr), f)
if linkrevs:
if f and len(linkrevs) > 1:
try:
# attempt to filter down to real linkrevs
linkrevs = [l for l in linkrevs
if self.lrugetctx(l)[f].filenode() == node]
except Exception:
pass
Pulkit Goyal
py3: use pycompat.bytestr() instead of str()...
r35603 self.warn(_(" (expected %s)") % " ".join
(map(pycompat.bytestr, linkrevs)))
Durham Goode
verify: move checkentry() to be a class function...
r27643 lr = None # can't be trusted
try:
p1, p2 = obj.parents(node)
if p1 not in seen and p1 != nullid:
self.err(lr, _("unknown parent 1 %s of %s") %
(short(p1), short(node)), f)
if p2 not in seen and p2 != nullid:
self.err(lr, _("unknown parent 2 %s of %s") %
(short(p2), short(node)), f)
except Exception as inst:
self.exc(lr, _("checking parents of %s") % short(node), inst, f)
if node in seen:
self.err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
seen[node] = i
return lr
Durham Goode
verify: move widely used variables into class members...
r27444 def verify(self):
repo = self.repo
Durham Goode
verify: get rid of some unnecessary local variables...
r27648
Durham Goode
verify: move verify logic into a class...
r27443 ui = repo.ui
Matt Mackall
Move repo.verify
r2778
Durham Goode
verify: move verify logic into a class...
r27443 if not repo.url().startswith('file:'):
raise error.Abort(_("cannot verify bundle or remote repos"))
Matt Mackall
verify: lots of refactoring...
r6752
Durham Goode
verify: move verify logic into a class...
r27443 if os.path.exists(repo.sjoin("journal")):
ui.warn(_("abandoned transaction found - run hg recover\n"))
Durham Goode
verify: get rid of some unnecessary local variables...
r27648 if ui.verbose or not self.revlogv1:
Durham Goode
verify: move verify logic into a class...
r27443 ui.status(_("repository uses revlog format %d\n") %
Durham Goode
verify: get rid of some unnecessary local variables...
r27648 (self.revlogv1 and 1 or 0))
Durham Goode
verify: move verify logic into a class...
r27443
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 mflinkrevs, filelinkrevs = self._verifychangelog()
Durham Goode
verify: move changelog verificaiton to its own function...
r27647
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 filenodes = self._verifymanifest(mflinkrevs)
Martin von Zweigbergk
verify: move cross-checking of changeset/manifest out of _crosscheckfiles()...
r28111 del mflinkrevs
Durham Goode
verify: move changelog verificaiton to its own function...
r27647
Martin von Zweigbergk
verify: move cross-checking of changeset/manifest out of _crosscheckfiles()...
r28111 self._crosscheckfiles(filelinkrevs, filenodes)
Durham Goode
verify: move changelog verificaiton to its own function...
r27647
totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs)
ui.status(_("%d files, %d changesets, %d total revisions\n") %
Durham Goode
verify: get rid of some unnecessary local variables...
r27648 (totalfiles, len(repo.changelog), filerevisions))
Durham Goode
verify: move changelog verificaiton to its own function...
r27647 if self.warnings:
ui.warn(_("%d warnings encountered!\n") % self.warnings)
if self.fncachewarned:
ui.warn(_('hint: run "hg debugrebuildfncache" to recover from '
'corrupt fncache\n'))
if self.errors:
ui.warn(_("%d integrity errors encountered!\n") % self.errors)
Durham Goode
verify: get rid of some unnecessary local variables...
r27648 if self.badrevs:
Durham Goode
verify: move changelog verificaiton to its own function...
r27647 ui.warn(_("(first damaged changeset appears to be %d)\n")
Durham Goode
verify: get rid of some unnecessary local variables...
r27648 % min(self.badrevs))
Durham Goode
verify: move changelog verificaiton to its own function...
r27647 return 1
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 def _verifychangelog(self):
Durham Goode
verify: move changelog verificaiton to its own function...
r27647 ui = self.ui
repo = self.repo
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 match = self.match
Durham Goode
verify: move changelog verificaiton to its own function...
r27647 cl = repo.changelog
Durham Goode
verify: move verify logic into a class...
r27443 ui.status(_("checking changesets\n"))
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 mflinkrevs = {}
filelinkrevs = {}
Durham Goode
verify: move verify logic into a class...
r27443 seen = {}
Durham Goode
verify: move checklog() onto class...
r27642 self.checklog(cl, "changelog", 0)
Durham Goode
verify: move verify logic into a class...
r27443 total = len(repo)
for i in repo:
ui.progress(_('checking'), i, total=total, unit=_('changesets'))
n = cl.node(i)
Durham Goode
verify: move checkentry() to be a class function...
r27643 self.checkentry(cl, i, n, seen, [i], "changelog")
Matt Mackall
Move repo.verify
r2778
Durham Goode
verify: move verify logic into a class...
r27443 try:
changes = cl.read(n)
if changes[0] != nullid:
mflinkrevs.setdefault(changes[0], []).append(i)
Durham Goode
verify: move widely used variables into class members...
r27444 self.refersmf = True
Durham Goode
verify: move verify logic into a class...
r27443 for f in changes[3]:
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 if match(f):
Durham Goode
verify: move verify logic into a class...
r27443 filelinkrevs.setdefault(_normpath(f), []).append(i)
except Exception as inst:
Durham Goode
verify: move widely used variables into class members...
r27444 self.refersmf = True
Durham Goode
verify: move exc() function onto class...
r27448 self.exc(i, _("unpacking changeset %s") % short(n), inst)
Durham Goode
verify: move verify logic into a class...
r27443 ui.progress(_('checking'), None)
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 return mflinkrevs, filelinkrevs
Matt Mackall
Move repo.verify
r2778
Martin von Zweigbergk
verify: show progress while verifying dirlogs...
r28205 def _verifymanifest(self, mflinkrevs, dir="", storefiles=None,
progress=None):
Durham Goode
verify: move manifest verification to its own function...
r27646 repo = self.repo
ui = self.ui
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 match = self.match
Durham Goode
manifest: remove manifest.readshallowdelta...
r30295 mfl = self.repo.manifestlog
mf = mfl._revlog.dirlog(dir)
Durham Goode
verify: move manifest verification to its own function...
r27646
Martin von Zweigbergk
verify: check directory manifests...
r28203 if not dir:
self.ui.status(_("checking manifests\n"))
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 filenodes = {}
Martin von Zweigbergk
verify: check directory manifests...
r28203 subdirnodes = {}
Durham Goode
verify: move verify logic into a class...
r27443 seen = {}
Martin von Zweigbergk
verify: extract "manifest" constant into variable...
r28115 label = "manifest"
Martin von Zweigbergk
verify: check directory manifests...
r28203 if dir:
label = dir
Martin von Zweigbergk
verify: check for orphaned dirlogs...
r28204 revlogfiles = mf.files()
storefiles.difference_update(revlogfiles)
Martin von Zweigbergk
verify: show progress while verifying dirlogs...
r28205 if progress: # should be true since we're in a subdirectory
progress()
Durham Goode
verify: move widely used variables into class members...
r27444 if self.refersmf:
Durham Goode
verify: move verify logic into a class...
r27443 # Do not check manifest if there are only changelog entries with
# null manifests.
Martin von Zweigbergk
verify: extract "manifest" constant into variable...
r28115 self.checklog(mf, label, 0)
Durham Goode
verify: move verify logic into a class...
r27443 total = len(mf)
for i in mf:
Martin von Zweigbergk
verify: check directory manifests...
r28203 if not dir:
ui.progress(_('checking'), i, total=total, unit=_('manifests'))
Durham Goode
verify: move verify logic into a class...
r27443 n = mf.node(i)
Martin von Zweigbergk
verify: extract "manifest" constant into variable...
r28115 lr = self.checkentry(mf, i, n, seen, mflinkrevs.get(n, []), label)
Durham Goode
verify: move verify logic into a class...
r27443 if n in mflinkrevs:
del mflinkrevs[n]
Martin von Zweigbergk
verify: check directory manifests...
r28203 elif dir:
self.err(lr, _("%s not in parent-directory manifest") %
short(n), label)
Durham Goode
verify: move verify logic into a class...
r27443 else:
Martin von Zweigbergk
verify: extract "manifest" constant into variable...
r28115 self.err(lr, _("%s not in changesets") % short(n), label)
Matt Mackall
Move repo.verify
r2778
Durham Goode
verify: move verify logic into a class...
r27443 try:
Durham Goode
manifest: remove manifest.readshallowdelta...
r30295 mfdelta = mfl.get(dir, n).readdelta(shallow=True)
for f, fn, fl in mfdelta.iterentries():
Durham Goode
verify: move verify logic into a class...
r27443 if not f:
Martin von Zweigbergk
verify: check directory manifests...
r28203 self.err(lr, _("entry without name in manifest"))
elif f == "/dev/null": # ignore this in very old repos
continue
fullpath = dir + _normpath(f)
if fl == 't':
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 if not match.visitdir(fullpath):
continue
Martin von Zweigbergk
verify: check directory manifests...
r28203 subdirnodes.setdefault(fullpath + '/', {}).setdefault(
fn, []).append(lr)
else:
Martin von Zweigbergk
verify: replace _validpath() by matcher...
r30866 if not match(fullpath):
continue
Martin von Zweigbergk
verify: check directory manifests...
r28203 filenodes.setdefault(fullpath, {}).setdefault(fn, lr)
Durham Goode
verify: move verify logic into a class...
r27443 except Exception as inst:
Martin von Zweigbergk
verify: extract "manifest" constant into variable...
r28115 self.exc(lr, _("reading delta %s") % short(n), inst, label)
Martin von Zweigbergk
verify: check directory manifests...
r28203 if not dir:
ui.progress(_('checking'), None)
Durham Goode
verify: move verify logic into a class...
r27443
Martin von Zweigbergk
verify: move cross-checking of changeset/manifest out of _crosscheckfiles()...
r28111 if self.havemf:
for c, m in sorted([(c, m) for m in mflinkrevs
for c in mflinkrevs[m]]):
Martin von Zweigbergk
verify: check directory manifests...
r28203 if dir:
self.err(c, _("parent-directory manifest refers to unknown "
"revision %s") % short(m), label)
else:
self.err(c, _("changeset refers to unknown revision %s") %
short(m), label)
if not dir and subdirnodes:
self.ui.status(_("checking directory manifests\n"))
Martin von Zweigbergk
verify: check for orphaned dirlogs...
r28204 storefiles = set()
Martin von Zweigbergk
verify: show progress while verifying dirlogs...
r28205 subdirs = set()
Martin von Zweigbergk
verify: check for orphaned dirlogs...
r28204 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))
Martin von Zweigbergk
verify: show progress while verifying dirlogs...
r28205 subdirs.add(os.path.dirname(f))
subdircount = len(subdirs)
currentsubdir = [0]
def progress():
currentsubdir[0] += 1
ui.progress(_('checking'), currentsubdir[0], total=subdircount,
unit=_('manifests'))
Martin von Zweigbergk
verify: check for orphaned dirlogs...
r28204
Martin von Zweigbergk
verify: check directory manifests...
r28203 for subdir, linkrevs in subdirnodes.iteritems():
Martin von Zweigbergk
verify: show progress while verifying dirlogs...
r28205 subdirfilenodes = self._verifymanifest(linkrevs, subdir, storefiles,
progress)
Martin von Zweigbergk
verify: check directory manifests...
r28203 for f, onefilenodes in subdirfilenodes.iteritems():
filenodes.setdefault(f, {}).update(onefilenodes)
Martin von Zweigbergk
verify: move cross-checking of changeset/manifest out of _crosscheckfiles()...
r28111
Martin von Zweigbergk
verify: check for orphaned dirlogs...
r28204 if not dir and subdirnodes:
Martin von Zweigbergk
verify: show progress while verifying dirlogs...
r28205 ui.progress(_('checking'), None)
Gregory Szorc
verify: allow suppressing warnings about extra files...
r37435 if self.warnorphanstorefiles:
for f in sorted(storefiles):
self.warn(_("warning: orphan data file '%s'") % f)
Martin von Zweigbergk
verify: check for orphaned dirlogs...
r28204
Martin von Zweigbergk
verify: replace "output parameters" by return values...
r27695 return filenodes
Durham Goode
verify: move file cross checking to its own function...
r27645
Martin von Zweigbergk
verify: move cross-checking of changeset/manifest out of _crosscheckfiles()...
r28111 def _crosscheckfiles(self, filelinkrevs, filenodes):
Durham Goode
verify: move file cross checking to its own function...
r27645 repo = self.repo
ui = self.ui
Durham Goode
verify: move verify logic into a class...
r27443 ui.status(_("crosschecking files in changesets and manifests\n"))
Matt Mackall
Move repo.verify
r2778
Martin von Zweigbergk
verify: move cross-checking of changeset/manifest out of _crosscheckfiles()...
r28111 total = len(filelinkrevs) + len(filenodes)
Durham Goode
verify: move verify logic into a class...
r27443 count = 0
Durham Goode
verify: move file cross checking to its own function...
r27645 if self.havemf:
Durham Goode
verify: move verify logic into a class...
r27443 for f in sorted(filelinkrevs):
count += 1
ui.progress(_('crosschecking'), count, total=total)
if f not in filenodes:
lr = filelinkrevs[f][0]
Durham Goode
verify: move err() to be a class function...
r27447 self.err(lr, _("in changeset but not in manifest"), f)
Adrian Buehlmann
verify: check repo.store
r6892
Durham Goode
verify: move file cross checking to its own function...
r27645 if self.havecl:
Durham Goode
verify: move verify logic into a class...
r27443 for f in sorted(filenodes):
count += 1
ui.progress(_('crosschecking'), count, total=total)
if f not in filelinkrevs:
try:
fl = repo.file(f)
lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
except Exception:
lr = None
Durham Goode
verify: move err() to be a class function...
r27447 self.err(lr, _("in manifest but not in changeset"), f)
Durham Goode
verify: move verify logic into a class...
r27443
ui.progress(_('crosschecking'), None)
Henrik Stuart
verify: avoid exception on missing file revlog...
r8291
Durham Goode
verify: move filelog verification to its own function...
r27644 def _verifyfiles(self, filenodes, filelinkrevs):
repo = self.repo
ui = self.ui
lrugetctx = self.lrugetctx
revlogv1 = self.revlogv1
havemf = self.havemf
Durham Goode
verify: move verify logic into a class...
r27443 ui.status(_("checking files\n"))
Henrik Stuart
verify: avoid exception on missing file revlog...
r8291
Durham Goode
verify: move verify logic into a class...
r27443 storefiles = set()
for f, f2, size in repo.store.datafiles():
if not f:
Durham Goode
verify: move err() to be a class function...
r27447 self.err(None, _("cannot decode filename '%s'") % f2)
Martin von Zweigbergk
treemanifests: fix streaming clone...
r28007 elif (size > 0 or not revlogv1) and f.startswith('data/'):
Durham Goode
verify: move verify logic into a class...
r27443 storefiles.add(_normpath(f))
Adrian Buehlmann
verify: check repo.store
r6892
Durham Goode
verify: move verify logic into a class...
r27443 files = sorted(set(filenodes) | set(filelinkrevs))
total = len(files)
Durham Goode
verify: move filelog verification to its own function...
r27644 revisions = 0
Durham Goode
verify: move verify logic into a class...
r27443 for i, f in enumerate(files):
av6
verify: specify unit for ui.progress when checking files
r28467 ui.progress(_('checking'), i, item=f, total=total, unit=_('files'))
Adrian Buehlmann
verify: check repo.store
r6892 try:
Durham Goode
verify: move verify logic into a class...
r27443 linkrevs = filelinkrevs[f]
Adrian Buehlmann
verify: check repo.store
r6892 except KeyError:
Durham Goode
verify: move verify logic into a class...
r27443 # in manifest but not in changelog
linkrevs = []
Matt Mackall
Move repo.verify
r2778
Durham Goode
verify: move verify logic into a class...
r27443 if linkrevs:
lr = linkrevs[0]
else:
lr = None
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: add rename link checking
r3744 try:
Durham Goode
verify: move verify logic into a class...
r27443 fl = repo.file(f)
except error.RevlogError as e:
Durham Goode
verify: move err() to be a class function...
r27447 self.err(lr, _("broken revlog! (%s)") % e, f)
Durham Goode
verify: move verify logic into a class...
r27443 continue
for ff in fl.files():
try:
storefiles.remove(ff)
except KeyError:
Gregory Szorc
verify: allow suppressing warnings about extra files...
r37435 if self.warnorphanstorefiles:
self.warn(_(" warning: revlog '%s' not in fncache!") %
ff)
self.fncachewarned = True
Durham Goode
verify: move verify logic into a class...
r27443
Durham Goode
verify: move checklog() onto class...
r27642 self.checklog(fl, f, lr)
Durham Goode
verify: move verify logic into a class...
r27443 seen = {}
rp = None
for i in fl:
revisions += 1
n = fl.node(i)
Durham Goode
verify: move checkentry() to be a class function...
r27643 lr = self.checkentry(fl, i, n, seen, linkrevs, f)
Durham Goode
verify: move verify logic into a class...
r27443 if f in filenodes:
if havemf and n not in filenodes[f]:
Durham Goode
verify: move err() to be a class function...
r27447 self.err(lr, _("%s not in manifests") % (short(n)), f)
Patrick Mezard
verify: check copy source revlog and nodeid
r6534 else:
Durham Goode
verify: move verify logic into a class...
r27443 del filenodes[f][n]
Jun Wu
verify: document corner cases...
r31761 # Verify contents. 4 cases to care about:
#
# common: the most common case
# rename: with a rename
# meta: file content starts with b'\1\n', the metadata
# header defined in filelog.py, but without a rename
# ext: content stored externally
#
# More formally, their differences are shown below:
#
# | common | rename | meta | ext
# -------------------------------------------------------
# flags() | 0 | 0 | 0 | not 0
# renamed() | False | True | False | ?
# rawtext[0:2]=='\1\n'| False | True | True | ?
#
# "rawtext" means the raw text stored in revlog data, which
# could be retrieved by "revision(rev, raw=True)". "text"
# mentioned below is "revision(rev, raw=False)".
#
# There are 3 different lengths stored physically:
# 1. L1: rawsize, stored in revlog index
# 2. L2: len(rawtext), stored in revlog data
# 3. L3: len(text), stored in revlog data if flags==0, or
# possibly somewhere else if flags!=0
#
# L1 should be equal to L2. L3 could be different from them.
# "text" may or may not affect commit hash depending on flag
# processors (see revlog.addflagprocessor).
#
# | common | rename | meta | ext
# -------------------------------------------------
# rawsize() | L1 | L1 | L1 | L1
# size() | L1 | L2-LM | L1(*) | L1 (?)
# len(rawtext) | L2 | L2 | L2 | L2
# len(text) | L2 | L2 | L2 | L3
# len(read()) | L2 | L2-LM | L2-LM | L3 (?)
#
# LM: length of metadata, depending on rawtext
# (*): not ideal, see comment in filelog.size
# (?): could be "- len(meta)" if the resolved content has
# rename metadata
#
# Checks needed to be done:
# 1. length check: L1 == L2, in all cases.
# 2. hash check: depending on flag processor, we may need to
# use either "text" (external), or "rawtext" (in revlog).
Durham Goode
verify: move verify logic into a class...
r27443 try:
Jun Wu
verify: add a config option to skip certain flag processors...
r32288 skipflags = self.skipflags
if skipflags:
skipflags &= fl.flags(i)
if not skipflags:
fl.read(n) # side effect: read content and do checkhash
rp = fl.renamed(n)
Jun Wu
verify: always check rawsize...
r32250 # the "L1 == L2" check
l1 = fl.rawsize(i)
l2 = len(fl.revision(n, raw=True))
if l1 != l2:
self.err(lr, _("unpacked size is %s, %s expected") %
(l2, l1), f)
Durham Goode
verify: move verify logic into a class...
r27443 except error.CensoredNodeError:
# experimental config: censor.policy
Jun Wu
codemod: register core configitems using a script...
r33499 if ui.config("censor", "policy") == "abort":
Durham Goode
verify: move err() to be a class function...
r27447 self.err(lr, _("censored file data"), f)
Durham Goode
verify: move verify logic into a class...
r27443 except Exception as inst:
Durham Goode
verify: move exc() function onto class...
r27448 self.exc(lr, _("unpacking %s") % short(n), inst, f)
Matt Mackall
verify: add rename link checking
r3744
Durham Goode
verify: move verify logic into a class...
r27443 # check renames
try:
if rp:
if lr is not None and ui.verbose:
ctx = lrugetctx(lr)
Martin von Zweigbergk
verify: don't reimplement any()...
r36357 if not any(rp[0] in pctx for pctx in ctx.parents()):
Durham Goode
verify: move warn() to a class level function...
r27446 self.warn(_("warning: copy source of '%s' not"
" in parents of %s") % (f, ctx))
Durham Goode
verify: move verify logic into a class...
r27443 fl2 = repo.file(rp[0])
if not len(fl2):
Durham Goode
verify: move err() to be a class function...
r27447 self.err(lr, _("empty or missing copy source "
"revlog %s:%s") % (rp[0], short(rp[1])), f)
Durham Goode
verify: move verify logic into a class...
r27443 elif rp[1] == nullid:
ui.note(_("warning: %s@%s: copy source"
" revision is nullid %s:%s\n")
% (f, lr, rp[0], short(rp[1])))
else:
fl2.rev(rp[1])
except Exception as inst:
Durham Goode
verify: move exc() function onto class...
r27448 self.exc(lr, _("checking rename of %s") % short(n), inst, f)
Adrian Buehlmann
verify: check repo.store
r6892
Durham Goode
verify: move verify logic into a class...
r27443 # cross-check
if f in filenodes:
Augie Fackler
verify: avoid shadowing two variables with a list comprehension...
r30393 fns = [(v, k) for k, v in filenodes[f].iteritems()]
Durham Goode
verify: move verify logic into a class...
r27443 for lr, node in sorted(fns):
Martin von Zweigbergk
verify: use similar language for missing manifest and file revisions...
r28114 self.err(lr, _("manifest refers to unknown revision %s") %
short(node), f)
Durham Goode
verify: move verify logic into a class...
r27443 ui.progress(_('checking'), None)
Gregory Szorc
verify: allow suppressing warnings about extra files...
r37435 if self.warnorphanstorefiles:
for f in sorted(storefiles):
self.warn(_("warning: orphan data file '%s'") % f)
Durham Goode
verify: move verify logic into a class...
r27443
Durham Goode
verify: move filelog verification to its own function...
r27644 return len(files), revisions