Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/verify.py @ 5173:7e05bdeee7de
convert: raise Abort instead of NoRepo when CVS pserver auth fails.
At this point we know the source is CVS, so we should not go through
the rest of the converters.
author | Brendan Cully <brendan@kublai.com> |
---|---|
date | Wed, 15 Aug 2007 14:38:18 -0700 |
parents | 97b734fb9c6f |
children | 012dbf88b9b2 |
rev | line source |
---|---|
2802 | 1 # verify.py - repository integrity checking for Mercurial |
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> |
2802 | 4 # |
5 # This software may be used and distributed according to the terms | |
6 # of the GNU General Public License, incorporated herein by reference. | |
7 | |
8 from node import * | |
3893 | 9 from i18n import _ |
2802 | 10 import revlog, mdiff |
11 | |
12 def verify(repo): | |
4959
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): |
2802 | 20 filelinkrevs = {} |
21 filenodes = {} | |
22 changesets = revisions = files = 0 | |
23 errors = [0] | |
24 warnings = [0] | |
25 neededmanifests = {} | |
26 | |
27 def err(msg): | |
28 repo.ui.warn(msg + "\n") | |
29 errors[0] += 1 | |
30 | |
31 def warn(msg): | |
32 repo.ui.warn(msg + "\n") | |
33 warnings[0] += 1 | |
34 | |
35 def checksize(obj, name): | |
36 d = obj.checksize() | |
37 if d[0]: | |
38 err(_("%s data length off by %d bytes") % (name, d[0])) | |
39 if d[1]: | |
40 err(_("%s index contains %d extra bytes") % (name, d[1])) | |
41 | |
42 def checkversion(obj, name): | |
43 if obj.version != revlog.REVLOGV0: | |
44 if not revlogv1: | |
45 warn(_("warning: `%s' uses revlog format 1") % name) | |
46 elif revlogv1: | |
47 warn(_("warning: `%s' uses revlog format 0") % name) | |
48 | |
4267
b11a2fb59cf5
revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents:
3893
diff
changeset
|
49 revlogv1 = repo.changelog.version != revlog.REVLOGV0 |
b11a2fb59cf5
revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents:
3893
diff
changeset
|
50 if repo.ui.verbose or not revlogv1: |
2802 | 51 repo.ui.status(_("repository uses revlog format %d\n") % |
52 (revlogv1 and 1 or 0)) | |
53 | |
54 seen = {} | |
55 repo.ui.status(_("checking changesets\n")) | |
56 checksize(repo.changelog, "changelog") | |
57 | |
3468
0e68608bd11d
use xrange instead of range
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3189
diff
changeset
|
58 for i in xrange(repo.changelog.count()): |
2802 | 59 changesets += 1 |
60 n = repo.changelog.node(i) | |
61 l = repo.changelog.linkrev(n) | |
62 if l != i: | |
63 err(_("incorrect link (%d) for changeset revision %d") %(l, i)) | |
64 if n in seen: | |
65 err(_("duplicate changeset at revision %d") % i) | |
66 seen[n] = 1 | |
67 | |
68 for p in repo.changelog.parents(n): | |
69 if p not in repo.changelog.nodemap: | |
70 err(_("changeset %s has unknown parent %s") % | |
71 (short(n), short(p))) | |
72 try: | |
73 changes = repo.changelog.read(n) | |
74 except KeyboardInterrupt: | |
75 repo.ui.warn(_("interrupted")) | |
76 raise | |
77 except Exception, inst: | |
78 err(_("unpacking changeset %s: %s") % (short(n), inst)) | |
79 continue | |
80 | |
81 neededmanifests[changes[0]] = n | |
82 | |
83 for f in changes[3]: | |
84 filelinkrevs.setdefault(f, []).append(i) | |
85 | |
86 seen = {} | |
87 repo.ui.status(_("checking manifests\n")) | |
88 checkversion(repo.manifest, "manifest") | |
89 checksize(repo.manifest, "manifest") | |
90 | |
3468
0e68608bd11d
use xrange instead of range
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3189
diff
changeset
|
91 for i in xrange(repo.manifest.count()): |
2802 | 92 n = repo.manifest.node(i) |
93 l = repo.manifest.linkrev(n) | |
94 | |
95 if l < 0 or l >= repo.changelog.count(): | |
96 err(_("bad manifest link (%d) at revision %d") % (l, i)) | |
97 | |
98 if n in neededmanifests: | |
99 del neededmanifests[n] | |
100 | |
101 if n in seen: | |
102 err(_("duplicate manifest at revision %d") % i) | |
103 | |
104 seen[n] = 1 | |
105 | |
106 for p in repo.manifest.parents(n): | |
107 if p not in repo.manifest.nodemap: | |
108 err(_("manifest %s has unknown parent %s") % | |
109 (short(n), short(p))) | |
110 | |
111 try: | |
3189
f3b939444c72
Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents:
2802
diff
changeset
|
112 for f, fn in repo.manifest.readdelta(n).iteritems(): |
f3b939444c72
Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents:
2802
diff
changeset
|
113 filenodes.setdefault(f, {})[fn] = 1 |
2802 | 114 except KeyboardInterrupt: |
115 repo.ui.warn(_("interrupted")) | |
116 raise | |
117 except Exception, inst: | |
3189
f3b939444c72
Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents:
2802
diff
changeset
|
118 err(_("reading delta for manifest %s: %s") % (short(n), inst)) |
2802 | 119 continue |
120 | |
121 repo.ui.status(_("crosschecking files in changesets and manifests\n")) | |
122 | |
123 for m, c in neededmanifests.items(): | |
124 err(_("Changeset %s refers to unknown manifest %s") % | |
125 (short(m), short(c))) | |
126 del neededmanifests | |
127 | |
128 for f in filenodes: | |
129 if f not in filelinkrevs: | |
130 err(_("file %s in manifest but not in changesets") % f) | |
131 | |
132 for f in filelinkrevs: | |
133 if f not in filenodes: | |
134 err(_("file %s in changeset but not in manifest") % f) | |
135 | |
136 repo.ui.status(_("checking files\n")) | |
137 ff = filenodes.keys() | |
138 ff.sort() | |
139 for f in ff: | |
140 if f == "/dev/null": | |
141 continue | |
142 files += 1 | |
143 if not f: | |
144 err(_("file without name in manifest %s") % short(n)) | |
145 continue | |
146 fl = repo.file(f) | |
147 checkversion(fl, f) | |
148 checksize(fl, f) | |
149 | |
150 nodes = {nullid: 1} | |
151 seen = {} | |
3468
0e68608bd11d
use xrange instead of range
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3189
diff
changeset
|
152 for i in xrange(fl.count()): |
2802 | 153 revisions += 1 |
154 n = fl.node(i) | |
155 | |
156 if n in seen: | |
157 err(_("%s: duplicate revision %d") % (f, i)) | |
158 if n not in filenodes[f]: | |
159 err(_("%s: %d:%s not in manifests") % (f, i, short(n))) | |
160 else: | |
161 del filenodes[f][n] | |
162 | |
163 flr = fl.linkrev(n) | |
164 if flr not in filelinkrevs.get(f, []): | |
165 err(_("%s:%s points to unexpected changeset %d") | |
166 % (f, short(n), flr)) | |
167 else: | |
168 filelinkrevs[f].remove(flr) | |
169 | |
170 # verify contents | |
171 try: | |
172 t = fl.read(n) | |
173 except KeyboardInterrupt: | |
174 repo.ui.warn(_("interrupted")) | |
175 raise | |
176 except Exception, inst: | |
177 err(_("unpacking file %s %s: %s") % (f, short(n), inst)) | |
178 | |
179 # verify parents | |
180 (p1, p2) = fl.parents(n) | |
181 if p1 not in nodes: | |
182 err(_("file %s:%s unknown parent 1 %s") % | |
183 (f, short(n), short(p1))) | |
184 if p2 not in nodes: | |
185 err(_("file %s:%s unknown parent 2 %s") % | |
186 (f, short(n), short(p1))) | |
187 nodes[n] = 1 | |
188 | |
3745
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
189 # check renames |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
190 try: |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
191 rp = fl.renamed(n) |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
192 if rp: |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
193 fl2 = repo.file(rp[0]) |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
194 rev = fl2.rev(rp[1]) |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
195 except KeyboardInterrupt: |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
196 repo.ui.warn(_("interrupted")) |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
197 raise |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
198 except Exception, inst: |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
199 err(_("checking rename on file %s %s: %s") % (f, short(n), inst)) |
d626fc9e3985
verify: add rename link checking
Matt Mackall <mpm@selenic.com>
parents:
3468
diff
changeset
|
200 |
2802 | 201 # cross-check |
202 for node in filenodes[f]: | |
203 err(_("node %s in manifests not in %s") % (hex(node), f)) | |
204 | |
205 repo.ui.status(_("%d files, %d changesets, %d total revisions\n") % | |
206 (files, changesets, revisions)) | |
207 | |
208 if warnings[0]: | |
209 repo.ui.warn(_("%d warnings encountered!\n") % warnings[0]) | |
210 if errors[0]: | |
211 repo.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) | |
212 return 1 | |
213 |