Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/verify.py @ 3409:1ae738bacf74
Fixed page overlap for file revision links in hgweb.
This is another step to fix issue189, but currently the file revision numbers
are read as changeset revision numbers, so the link will point to the wrong
revision.
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Mon, 16 Oct 2006 09:53:31 +0200 |
parents | f3b939444c72 |
children | 0e68608bd11d |
rev | line source |
---|---|
2802 | 1 # verify.py - repository integrity checking for Mercurial |
2 # | |
3 # Copyright 2006 Matt Mackall <mpm@selenic.com> | |
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 * | |
9 from i18n import gettext as _ | |
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 | |
20 def err(msg): | |
21 repo.ui.warn(msg + "\n") | |
22 errors[0] += 1 | |
23 | |
24 def warn(msg): | |
25 repo.ui.warn(msg + "\n") | |
26 warnings[0] += 1 | |
27 | |
28 def checksize(obj, name): | |
29 d = obj.checksize() | |
30 if d[0]: | |
31 err(_("%s data length off by %d bytes") % (name, d[0])) | |
32 if d[1]: | |
33 err(_("%s index contains %d extra bytes") % (name, d[1])) | |
34 | |
35 def checkversion(obj, name): | |
36 if obj.version != revlog.REVLOGV0: | |
37 if not revlogv1: | |
38 warn(_("warning: `%s' uses revlog format 1") % name) | |
39 elif revlogv1: | |
40 warn(_("warning: `%s' uses revlog format 0") % name) | |
41 | |
42 revlogv1 = repo.revlogversion != revlog.REVLOGV0 | |
43 if repo.ui.verbose or revlogv1 != repo.revlogv1: | |
44 repo.ui.status(_("repository uses revlog format %d\n") % | |
45 (revlogv1 and 1 or 0)) | |
46 | |
47 seen = {} | |
48 repo.ui.status(_("checking changesets\n")) | |
49 checksize(repo.changelog, "changelog") | |
50 | |
51 for i in range(repo.changelog.count()): | |
52 changesets += 1 | |
53 n = repo.changelog.node(i) | |
54 l = repo.changelog.linkrev(n) | |
55 if l != i: | |
56 err(_("incorrect link (%d) for changeset revision %d") %(l, i)) | |
57 if n in seen: | |
58 err(_("duplicate changeset at revision %d") % i) | |
59 seen[n] = 1 | |
60 | |
61 for p in repo.changelog.parents(n): | |
62 if p not in repo.changelog.nodemap: | |
63 err(_("changeset %s has unknown parent %s") % | |
64 (short(n), short(p))) | |
65 try: | |
66 changes = repo.changelog.read(n) | |
67 except KeyboardInterrupt: | |
68 repo.ui.warn(_("interrupted")) | |
69 raise | |
70 except Exception, inst: | |
71 err(_("unpacking changeset %s: %s") % (short(n), inst)) | |
72 continue | |
73 | |
74 neededmanifests[changes[0]] = n | |
75 | |
76 for f in changes[3]: | |
77 filelinkrevs.setdefault(f, []).append(i) | |
78 | |
79 seen = {} | |
80 repo.ui.status(_("checking manifests\n")) | |
81 checkversion(repo.manifest, "manifest") | |
82 checksize(repo.manifest, "manifest") | |
83 | |
84 for i in range(repo.manifest.count()): | |
85 n = repo.manifest.node(i) | |
86 l = repo.manifest.linkrev(n) | |
87 | |
88 if l < 0 or l >= repo.changelog.count(): | |
89 err(_("bad manifest link (%d) at revision %d") % (l, i)) | |
90 | |
91 if n in neededmanifests: | |
92 del neededmanifests[n] | |
93 | |
94 if n in seen: | |
95 err(_("duplicate manifest at revision %d") % i) | |
96 | |
97 seen[n] = 1 | |
98 | |
99 for p in repo.manifest.parents(n): | |
100 if p not in repo.manifest.nodemap: | |
101 err(_("manifest %s has unknown parent %s") % | |
102 (short(n), short(p))) | |
103 | |
104 try: | |
3189
f3b939444c72
Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents:
2802
diff
changeset
|
105 for f, fn in repo.manifest.readdelta(n).iteritems(): |
f3b939444c72
Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents:
2802
diff
changeset
|
106 filenodes.setdefault(f, {})[fn] = 1 |
2802 | 107 except KeyboardInterrupt: |
108 repo.ui.warn(_("interrupted")) | |
109 raise | |
110 except Exception, inst: | |
3189
f3b939444c72
Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents:
2802
diff
changeset
|
111 err(_("reading delta for manifest %s: %s") % (short(n), inst)) |
2802 | 112 continue |
113 | |
114 repo.ui.status(_("crosschecking files in changesets and manifests\n")) | |
115 | |
116 for m, c in neededmanifests.items(): | |
117 err(_("Changeset %s refers to unknown manifest %s") % | |
118 (short(m), short(c))) | |
119 del neededmanifests | |
120 | |
121 for f in filenodes: | |
122 if f not in filelinkrevs: | |
123 err(_("file %s in manifest but not in changesets") % f) | |
124 | |
125 for f in filelinkrevs: | |
126 if f not in filenodes: | |
127 err(_("file %s in changeset but not in manifest") % f) | |
128 | |
129 repo.ui.status(_("checking files\n")) | |
130 ff = filenodes.keys() | |
131 ff.sort() | |
132 for f in ff: | |
133 if f == "/dev/null": | |
134 continue | |
135 files += 1 | |
136 if not f: | |
137 err(_("file without name in manifest %s") % short(n)) | |
138 continue | |
139 fl = repo.file(f) | |
140 checkversion(fl, f) | |
141 checksize(fl, f) | |
142 | |
143 nodes = {nullid: 1} | |
144 seen = {} | |
145 for i in range(fl.count()): | |
146 revisions += 1 | |
147 n = fl.node(i) | |
148 | |
149 if n in seen: | |
150 err(_("%s: duplicate revision %d") % (f, i)) | |
151 if n not in filenodes[f]: | |
152 err(_("%s: %d:%s not in manifests") % (f, i, short(n))) | |
153 else: | |
154 del filenodes[f][n] | |
155 | |
156 flr = fl.linkrev(n) | |
157 if flr not in filelinkrevs.get(f, []): | |
158 err(_("%s:%s points to unexpected changeset %d") | |
159 % (f, short(n), flr)) | |
160 else: | |
161 filelinkrevs[f].remove(flr) | |
162 | |
163 # verify contents | |
164 try: | |
165 t = fl.read(n) | |
166 except KeyboardInterrupt: | |
167 repo.ui.warn(_("interrupted")) | |
168 raise | |
169 except Exception, inst: | |
170 err(_("unpacking file %s %s: %s") % (f, short(n), inst)) | |
171 | |
172 # verify parents | |
173 (p1, p2) = fl.parents(n) | |
174 if p1 not in nodes: | |
175 err(_("file %s:%s unknown parent 1 %s") % | |
176 (f, short(n), short(p1))) | |
177 if p2 not in nodes: | |
178 err(_("file %s:%s unknown parent 2 %s") % | |
179 (f, short(n), short(p1))) | |
180 nodes[n] = 1 | |
181 | |
182 # cross-check | |
183 for node in filenodes[f]: | |
184 err(_("node %s in manifests not in %s") % (hex(node), f)) | |
185 | |
186 repo.ui.status(_("%d files, %d changesets, %d total revisions\n") % | |
187 (files, changesets, revisions)) | |
188 | |
189 if warnings[0]: | |
190 repo.ui.warn(_("%d warnings encountered!\n") % warnings[0]) | |
191 if errors[0]: | |
192 repo.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) | |
193 return 1 | |
194 |