##// END OF EJS Templates
diff: pass contexts to status...
diff: pass contexts to status Allow status() to take contexts as well as nodes. This lets us avoid unpacking manifests multiple times and intelligently unpack manifests in revision order. Also, we can avoid unpacking manifests at all when there are no changes in the working directory.

File last commit:

r7004:90227c42 default
r7090:7b5c063b default
Show More
verify.py
235 lines | 7.6 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 #
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Joel Rosdahl
Expand import * to allow Pyflakes to find problems
r6211 from node import nullid, short
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Matt Mackall
util: add sort helper
r6762 import revlog, util
Matt Mackall
Move repo.verify
r2778
def verify(repo):
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 lock = repo.lock()
try:
return _verify(repo)
finally:
del lock
def _verify(repo):
Matt Mackall
verify: lots of refactoring...
r6752 mflinkrevs = {}
Matt Mackall
Move repo.verify
r2778 filelinkrevs = {}
filenodes = {}
Matt Mackall
verify: lots of refactoring...
r6752 revisions = 0
badrevs = {}
Matt Mackall
Move repo.verify
r2778 errors = [0]
warnings = [0]
Matt Mackall
verify: add some local variables
r6751 ui = repo.ui
cl = repo.changelog
mf = repo.manifest
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: report first bad changeset...
r5313 def err(linkrev, msg, filename=None):
if linkrev != None:
Matt Mackall
verify: lots of refactoring...
r6752 badrevs[linkrev] = True
Matt Mackall
verify: report first bad changeset...
r5313 else:
Matt Mackall
verify: lots of refactoring...
r6752 linkrev = '?'
Matt Mackall
verify: report first bad changeset...
r5313 msg = "%s: %s" % (linkrev, msg)
if filename:
msg = "%s@%s" % (filename, msg)
Matt Mackall
verify: add some local variables
r6751 ui.warn(" " + msg + "\n")
Matt Mackall
Move repo.verify
r2778 errors[0] += 1
Matt Mackall
verify: lots of refactoring...
r6752 def exc(linkrev, msg, inst, filename=None):
if isinstance(inst, KeyboardInterrupt):
ui.warn(_("interrupted"))
raise
err(linkrev, "%s: %s" % (msg, inst), filename)
Matt Mackall
Move repo.verify
r2778 def warn(msg):
Matt Mackall
verify: add some local variables
r6751 ui.warn(msg + "\n")
Matt Mackall
Move repo.verify
r2778 warnings[0] += 1
Matt Mackall
verify: lots of refactoring...
r6752 def checklog(obj, name):
if not len(obj) and (havecl or havemf):
err(0, _("empty or missing %s") % name)
return
Matt Mackall
Move repo.verify
r2778 d = obj.checksize()
if d[0]:
Matt Mackall
verify: report first bad changeset...
r5313 err(None, _("data length off by %d bytes") % d[0], name)
Matt Mackall
Move repo.verify
r2778 if d[1]:
Matt Mackall
verify: report first bad changeset...
r5313 err(None, _("index contains %d extra bytes") % d[1], name)
Matt Mackall
Move repo.verify
r2778
if obj.version != revlog.REVLOGV0:
if not revlogv1:
warn(_("warning: `%s' uses revlog format 1") % name)
elif revlogv1:
warn(_("warning: `%s' uses revlog format 0") % name)
Matt Mackall
verify: lots of refactoring...
r6752 def checkentry(obj, i, node, seen, linkrevs, f):
lr = obj.linkrev(node)
if lr < 0 or (havecl and lr not in linkrevs):
t = "unexpected"
if lr < 0 or lr >= len(cl):
t = "nonexistent"
err(None, _("rev %d point to %s changeset %d") % (i, t, lr), f)
if linkrevs:
warn(_(" (expected %s)") % " ".join(map(str,linkrevs)))
lr = None # can't be trusted
try:
p1, p2 = obj.parents(node)
if p1 not in seen and p1 != nullid:
err(lr, _("unknown parent 1 %s of %s") %
(short(p1), short(n)), f)
if p2 not in seen and p2 != nullid:
err(lr, _("unknown parent 2 %s of %s") %
(short(p2), short(p1)), f)
except Exception, inst:
exc(lr, _("checking parents of %s") % short(node), inst, f)
if node in seen:
err(lr, _("duplicate revision %d (%d)") % (i, seen[n]), f)
seen[n] = i
return lr
Matt Mackall
verify: add some local variables
r6751 revlogv1 = cl.version != revlog.REVLOGV0
if ui.verbose or not revlogv1:
ui.status(_("repository uses revlog format %d\n") %
Matt Mackall
Move repo.verify
r2778 (revlogv1 and 1 or 0))
Matt Mackall
verify: lots of refactoring...
r6752 havecl = len(cl) > 0
havemf = len(mf) > 0
Matt Mackall
verify: add some local variables
r6751 ui.status(_("checking changesets\n"))
Matt Mackall
verify: lots of refactoring...
r6752 seen = {}
checklog(cl, "changelog")
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for i in repo:
Matt Mackall
verify: add some local variables
r6751 n = cl.node(i)
Matt Mackall
verify: lots of refactoring...
r6752 checkentry(cl, i, n, seen, [i], "changelog")
Matt Mackall
Move repo.verify
r2778
try:
Matt Mackall
verify: add some local variables
r6751 changes = cl.read(n)
Matt Mackall
verify: lots of refactoring...
r6752 mflinkrevs.setdefault(changes[0], []).append(i)
for f in changes[3]:
filelinkrevs.setdefault(f, []).append(i)
Matt Mackall
Move repo.verify
r2778 except Exception, inst:
Matt Mackall
verify: lots of refactoring...
r6752 exc(i, _("unpacking changeset %s") % short(n), inst)
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: lots of refactoring...
r6752 ui.status(_("checking manifests\n"))
Matt Mackall
Move repo.verify
r2778 seen = {}
Matt Mackall
verify: lots of refactoring...
r6752 checklog(mf, "manifest")
Matt Mackall
verify: add some local variables
r6751 for i in mf:
n = mf.node(i)
Matt Mackall
verify: lots of refactoring...
r6752 lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest")
if n in mflinkrevs:
del mflinkrevs[n]
Matt Mackall
Move repo.verify
r2778
try:
Matt Mackall
verify: add some local variables
r6751 for f, fn in mf.readdelta(n).iteritems():
Matt Mackall
verify: lots of refactoring...
r6752 if not f:
err(lr, _("file without name in manifest"))
elif f != "/dev/null":
fns = filenodes.setdefault(f, {})
if fn not in fns:
fns[fn] = n
Matt Mackall
Move repo.verify
r2778 except Exception, inst:
Matt Mackall
verify: lots of refactoring...
r6752 exc(lr, _("reading manifest delta %s") % short(n), inst)
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: add some local variables
r6751 ui.status(_("crosschecking files in changesets and manifests\n"))
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: lots of refactoring...
r6752 if havemf:
Matt Mackall
util: add sort helper
r6762 for c, m in util.sort([(c, m) for m in mflinkrevs for c in mflinkrevs[m]]):
Matt Mackall
verify: improve handling of empty or missing files...
r5541 err(c, _("changeset refers to unknown manifest %s") % short(m))
Matt Mackall
util: add sort helper
r6762 del mflinkrevs
Matt Mackall
Move repo.verify
r2778
Matt Mackall
util: add sort helper
r6762 for f in util.sort(filelinkrevs):
Matt Mackall
verify: improve handling of empty or missing files...
r5541 if f not in filenodes:
lr = filelinkrevs[f][0]
err(lr, _("in changeset but not in manifest"), f)
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: lots of refactoring...
r6752 if havecl:
Matt Mackall
util: add sort helper
r6762 for f in util.sort(filenodes):
Matt Mackall
verify: lots of refactoring...
r6752 if f not in filelinkrevs:
try:
lr = min([repo.file(f).linkrev(n) for n in filenodes[f]])
except:
lr = None
err(lr, _("in manifest but not in changeset"), f)
Matt Mackall
verify: add some local variables
r6751 ui.status(_("checking files\n"))
Adrian Buehlmann
verify: check repo.store
r6892
Matt Mackall
store: change handling of decoding errors
r6900 storefiles = {}
for f, f2, size in repo.store.datafiles():
if not f:
err(None, _("cannot decode filename '%s'") % f2)
elif size > 0:
Adrian Buehlmann
verify: check repo.store
r6892 storefiles[f] = True
Matt Mackall
util: add sort helper
r6762 files = util.sort(util.unique(filenodes.keys() + filelinkrevs.keys()))
Matt Mackall
verify: lots of refactoring...
r6752 for f in files:
Matt Mackall
Move repo.verify
r2778 fl = repo.file(f)
Adrian Buehlmann
verify: check repo.store
r6892
Matt Mackall
store: change handling of decoding errors
r6900 for ff in fl.files():
Adrian Buehlmann
verify: check repo.store
r6892 try:
del storefiles[ff]
except KeyError:
err(0, _("missing revlog!"), ff)
Matt Mackall
verify: lots of refactoring...
r6752 checklog(fl, f)
Matt Mackall
verify: report first bad changeset...
r5313 seen = {}
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for i in fl:
Matt Mackall
Move repo.verify
r2778 revisions += 1
n = fl.node(i)
Matt Mackall
verify: lots of refactoring...
r6752 lr = checkentry(fl, i, n, seen, filelinkrevs.get(f, []), f)
Matt Mackall
verify: improve handling of empty or missing files...
r5541 if f in filenodes:
if havemf and n not in filenodes[f]:
Matt Mackall
verify: lots of refactoring...
r6752 err(lr, _("%s not in manifests") % (short(n)), f)
Matt Mackall
verify: improve handling of empty or missing files...
r5541 else:
del filenodes[f][n]
Matt Mackall
Move repo.verify
r2778
# verify contents
try:
t = fl.read(n)
Matt Mackall
verify: lots of refactoring...
r6752 rp = fl.renamed(n)
if len(t) != fl.size(i):
if not fl._readmeta(n): # ancient copy?
err(lr, _("unpacked size is %s, %s expected") %
(len(t), fl.size(i)), f)
Matt Mackall
Move repo.verify
r2778 except Exception, inst:
Matt Mackall
verify: lots of refactoring...
r6752 exc(lr, _("unpacking %s") % short(n), inst, f)
Matt Mackall
Move repo.verify
r2778
Matt Mackall
verify: add rename link checking
r3744 # check renames
try:
if rp:
fl2 = repo.file(rp[0])
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if not len(fl2):
Matt Mackall
verify: lots of refactoring...
r6752 err(lr, _("empty or missing copy source revlog %s:%s")
Patrick Mezard
verify: check copy source revlog and nodeid
r6534 % (rp[0], short(rp[1])), f)
elif rp[1] == nullid:
Benoit Boissinot
c0bd7d8b69ef uses err() instead of warn() but prototype doesn't match...
r7004 warn(_("warning: %s@%s: copy source revision is nullid %s:%s")
% (f, lr, rp[0], short(rp[1])))
Patrick Mezard
verify: check copy source revlog and nodeid
r6534 else:
rev = fl2.rev(rp[1])
Matt Mackall
verify: add rename link checking
r3744 except Exception, inst:
Matt Mackall
verify: lots of refactoring...
r6752 exc(lr, _("checking rename of %s") % short(n), inst, f)
Matt Mackall
verify: add rename link checking
r3744
Matt Mackall
Move repo.verify
r2778 # cross-check
Matt Mackall
verify: improve handling of empty or missing files...
r5541 if f in filenodes:
Matt Mackall
verify: lots of refactoring...
r6752 fns = [(mf.linkrev(l), n) for n,l in filenodes[f].items()]
Matt Mackall
util: add sort helper
r6762 for lr, node in util.sort(fns):
Matt Mackall
verify: improve handling of empty or missing files...
r5541 err(lr, _("%s in manifests not found") % short(node), f)
Matt Mackall
Move repo.verify
r2778
Adrian Buehlmann
verify: check repo.store
r6892 for f in storefiles:
warn(_("warning: orphan revlog '%s'") % f)
Matt Mackall
verify: add some local variables
r6751 ui.status(_("%d files, %d changesets, %d total revisions\n") %
Matt Mackall
verify: lots of refactoring...
r6752 (len(files), len(cl), revisions))
Matt Mackall
Move repo.verify
r2778 if warnings[0]:
Matt Mackall
verify: add some local variables
r6751 ui.warn(_("%d warnings encountered!\n") % warnings[0])
Matt Mackall
Move repo.verify
r2778 if errors[0]:
Matt Mackall
verify: add some local variables
r6751 ui.warn(_("%d integrity errors encountered!\n") % errors[0])
Matt Mackall
verify: lots of refactoring...
r6752 if badrevs:
Matt Mackall
verify: add some local variables
r6751 ui.warn(_("(first damaged changeset appears to be %d)\n")
Matt Mackall
verify: lots of refactoring...
r6752 % min(badrevs))
Matt Mackall
Move repo.verify
r2778 return 1