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