mercurial/verify.py
author Christian Ebert <blacktrash@gmx.net>
Sun, 10 Feb 2008 04:24:59 +0100
changeset 6072 e521ec1ad985
parent 5541 ceaa752fa316
child 6211 f89fd07fc51d
permissions -rw-r--r--
keyword: no expansion in web diffs Expansion in hgweb view of changesets and diffs is not needed and only distracting. Expansion stays enable in file and archive requests where it makes sense.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# verify.py - repository integrity checking for Mercurial
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4395
diff changeset
     3
# Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
from node import *
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3744
diff changeset
     9
from i18n import _
5175
012dbf88b9b2 remove unneeded imports of mdiff
Matt Mackall <mpm@selenic.com>
parents: 4915
diff changeset
    10
import revlog
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
def verify(repo):
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    13
    lock = repo.lock()
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    14
    try:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    15
        return _verify(repo)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    16
    finally:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    17
        del lock
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    18
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
    19
def _verify(repo):
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
    filelinkrevs = {}
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
    filenodes = {}
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
    changesets = revisions = files = 0
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    23
    firstbad = [None]
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
    errors = [0]
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
    warnings = [0]
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
    neededmanifests = {}
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    28
    def err(linkrev, msg, filename=None):
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    29
        if linkrev != None:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    30
            if firstbad[0] != None:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    31
                firstbad[0] = min(firstbad[0], linkrev)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    32
            else:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    33
                firstbad[0] = linkrev
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    34
        else:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    35
            linkrev = "?"
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    36
        msg = "%s: %s" % (linkrev, msg)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    37
        if filename:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    38
            msg = "%s@%s" % (filename, msg)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    39
        repo.ui.warn(" " + msg + "\n")
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
        errors[0] += 1
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
    def warn(msg):
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
        repo.ui.warn(msg + "\n")
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
        warnings[0] += 1
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
    def checksize(obj, name):
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
        d = obj.checksize()
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
        if d[0]:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    49
            err(None, _("data length off by %d bytes") % d[0], name)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
        if d[1]:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    51
            err(None, _("index contains %d extra bytes") % d[1], name)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
    def checkversion(obj, name):
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
        if obj.version != revlog.REVLOGV0:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
            if not revlogv1:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
                warn(_("warning: `%s' uses revlog format 1") % name)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
        elif revlogv1:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
            warn(_("warning: `%s' uses revlog format 0") % name)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
4258
b11a2fb59cf5 revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents: 3891
diff changeset
    60
    revlogv1 = repo.changelog.version != revlog.REVLOGV0
b11a2fb59cf5 revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents: 3891
diff changeset
    61
    if repo.ui.verbose or not revlogv1:
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
        repo.ui.status(_("repository uses revlog format %d\n") %
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
                       (revlogv1 and 1 or 0))
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
    65
    havecl = havemf = 1
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
    seen = {}
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
    repo.ui.status(_("checking changesets\n"))
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
    68
    if repo.changelog.count() == 0 and repo.manifest.count() > 1:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
    69
        havecl = 0
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
    70
        err(0, _("empty or missing 00changelog.i"))
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
    71
    else:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
    72
        checksize(repo.changelog, "changelog")
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
3473
0e68608bd11d use xrange instead of range
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3196
diff changeset
    74
    for i in xrange(repo.changelog.count()):
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
        changesets += 1
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
        n = repo.changelog.node(i)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
        l = repo.changelog.linkrev(n)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
        if l != i:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    79
            err(i, _("incorrect link (%d) for changeset") %(l))
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
        if n in seen:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    81
            err(i, _("duplicates changeset at revision %d") % seen[n])
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    82
        seen[n] = i
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
        for p in repo.changelog.parents(n):
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
            if p not in repo.changelog.nodemap:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    86
                err(i, _("changeset has unknown parent %s") % short(p))
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
        try:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
            changes = repo.changelog.read(n)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
        except KeyboardInterrupt:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
            repo.ui.warn(_("interrupted"))
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
            raise
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
        except Exception, inst:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    93
            err(i, _("unpacking changeset: %s") % inst)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    94
            continue
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    96
        if changes[0] not in neededmanifests:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
    97
            neededmanifests[changes[0]] = i
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
        for f in changes[3]:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
            filelinkrevs.setdefault(f, []).append(i)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
    seen = {}
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
    repo.ui.status(_("checking manifests\n"))
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   104
    if repo.changelog.count() > 0 and repo.manifest.count() == 0:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   105
        havemf = 0
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   106
        err(0, _("empty or missing 00manifest.i"))
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   107
    else:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   108
        checkversion(repo.manifest, "manifest")
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   109
        checksize(repo.manifest, "manifest")
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
3473
0e68608bd11d use xrange instead of range
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3196
diff changeset
   111
    for i in xrange(repo.manifest.count()):
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
        n = repo.manifest.node(i)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
        l = repo.manifest.linkrev(n)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   115
        if l < 0 or (havecl and l >= repo.changelog.count()):
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   116
            err(None, _("bad link (%d) at manifest revision %d") % (l, i))
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
        if n in neededmanifests:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
            del neededmanifests[n]
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
        if n in seen:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   122
            err(l, _("duplicates manifest from %d") % seen[n])
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   124
        seen[n] = l
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
        for p in repo.manifest.parents(n):
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127
            if p not in repo.manifest.nodemap:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   128
                err(l, _("manifest has unknown parent %s") % short(p))
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   129
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
        try:
3196
f3b939444c72 Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents: 2778
diff changeset
   131
            for f, fn in repo.manifest.readdelta(n).iteritems():
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   132
                fns = filenodes.setdefault(f, {})
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   133
                if fn not in fns:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   134
                    fns[fn] = n
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   135
        except KeyboardInterrupt:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   136
            repo.ui.warn(_("interrupted"))
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   137
            raise
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   138
        except Exception, inst:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   139
            err(l, _("reading manifest delta: %s") % inst)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   140
            continue
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   141
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   142
    repo.ui.status(_("crosschecking files in changesets and manifests\n"))
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   143
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   144
    if havemf > 0:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   145
        nm = [(c, m) for m, c in neededmanifests.items()]
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   146
        nm.sort()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   147
        for c, m in nm:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   148
            err(c, _("changeset refers to unknown manifest %s") % short(m))
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   149
        del neededmanifests, nm
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   150
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   151
    if havecl:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   152
        fl = filenodes.keys()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   153
        fl.sort()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   154
        for f in fl:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   155
            if f not in filelinkrevs:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   156
                lrs = [repo.manifest.linkrev(n) for n in filenodes[f]]
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   157
                lrs.sort()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   158
                err(lrs[0], _("in manifest but not in changeset"), f)
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   159
        del fl
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   160
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   161
    if havemf:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   162
        fl = filelinkrevs.keys()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   163
        fl.sort()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   164
        for f in fl:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   165
            if f not in filenodes:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   166
                lr = filelinkrevs[f][0]
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   167
                err(lr, _("in changeset but not in manifest"), f)
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   168
        del fl
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   170
    repo.ui.status(_("checking files\n"))
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   171
    ff = dict.fromkeys(filenodes.keys() + filelinkrevs.keys()).keys()
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   172
    ff.sort()
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   173
    for f in ff:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   174
        if f == "/dev/null":
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   175
            continue
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   176
        files += 1
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   177
        if not f:
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   178
            lr = filelinkrevs[f][0]
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   179
            err(lr, _("file without name in manifest"))
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   180
            continue
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
        fl = repo.file(f)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   182
        checkversion(fl, f)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   183
        checksize(fl, f)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   184
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   185
        if fl.count() == 0:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   186
            err(filelinkrevs[f][0], _("empty or missing revlog"), f)
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   187
            continue
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   188
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   189
        seen = {}
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   190
        nodes = {nullid: 1}
3473
0e68608bd11d use xrange instead of range
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3196
diff changeset
   191
        for i in xrange(fl.count()):
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   192
            revisions += 1
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
            n = fl.node(i)
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   194
            flr = fl.linkrev(n)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   195
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   196
            if flr < 0 or (havecl and flr not in filelinkrevs.get(f, [])):
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   197
                if flr < 0 or flr >= repo.changelog.count():
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   198
                    err(None, _("rev %d point to nonexistent changeset %d")
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   199
                        % (i, flr), f)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   200
                else:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   201
                    err(None, _("rev %d points to unexpected changeset %d")
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   202
                        % (i, flr), f)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   203
                if f in filelinkrevs:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   204
                    warn(_(" (expected %s)") % filelinkrevs[f][0])
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   205
                flr = None # can't be trusted
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   206
            else:
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   207
                if havecl:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   208
                    filelinkrevs[f].remove(flr)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   209
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   210
            if n in seen:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   211
                err(flr, _("duplicate revision %d") % i, f)
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   212
            if f in filenodes:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   213
                if havemf and n not in filenodes[f]:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   214
                    err(flr, _("%s not in manifests") % (short(n)), f)
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   215
                else:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   216
                    del filenodes[f][n]
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   217
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   218
            # verify contents
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   219
            try:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   220
                t = fl.read(n)
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   221
            except KeyboardInterrupt:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   222
                repo.ui.warn(_("interrupted"))
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   223
                raise
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   224
            except Exception, inst:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   225
                err(flr, _("unpacking %s: %s") % (short(n), inst), f)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   226
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   227
            # verify parents
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   228
            try:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   229
                (p1, p2) = fl.parents(n)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   230
                if p1 not in nodes:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   231
                    err(flr, _("unknown parent 1 %s of %s") %
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   232
                        (short(p1), short(n)), f)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   233
                if p2 not in nodes:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   234
                    err(flr, _("unknown parent 2 %s of %s") %
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   235
                            (short(p2), short(p1)), f)
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   236
            except KeyboardInterrupt:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   237
                repo.ui.warn(_("interrupted"))
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   238
                raise
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   239
            except Exception, inst:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   240
                err(flr, _("checking parents of %s: %s") % (short(n), inst), f)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   241
            nodes[n] = 1
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   242
3744
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   243
            # check renames
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   244
            try:
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   245
                rp = fl.renamed(n)
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   246
                if rp:
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   247
                    fl2 = repo.file(rp[0])
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   248
                    rev = fl2.rev(rp[1])
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   249
            except KeyboardInterrupt:
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   250
                repo.ui.warn(_("interrupted"))
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   251
                raise
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   252
            except Exception, inst:
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   253
                err(flr, _("checking rename of %s: %s") %
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   254
                    (short(n), inst), f)
3744
d626fc9e3985 verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents: 3473
diff changeset
   255
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   256
        # cross-check
5541
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   257
        if f in filenodes:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   258
            fns = [(repo.manifest.linkrev(filenodes[f][n]), n)
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   259
                   for n in filenodes[f]]
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   260
            fns.sort()
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   261
            for lr, node in fns:
ceaa752fa316 verify: improve handling of empty or missing files
Matt Mackall <mpm@selenic.com>
parents: 5313
diff changeset
   262
                err(lr, _("%s in manifests not found") % short(node), f)
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   263
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   264
    repo.ui.status(_("%d files, %d changesets, %d total revisions\n") %
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   265
                   (files, changesets, revisions))
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   266
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   267
    if warnings[0]:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   268
        repo.ui.warn(_("%d warnings encountered!\n") % warnings[0])
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   269
    if errors[0]:
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   270
        repo.ui.warn(_("%d integrity errors encountered!\n") % errors[0])
5313
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   271
        if firstbad[0]:
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   272
            repo.ui.warn(_("(first damaged changeset appears to be %d)\n")
29be4228303b verify: report first bad changeset
Matt Mackall <mpm@selenic.com>
parents: 5179
diff changeset
   273
                         % firstbad[0])
2778
fdc232d8a193 Move repo.verify
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   274
        return 1