Mercurial > public > mercurial-scm > hg
comparison mercurial/verify.py @ 27447:d1b91c10ce70
verify: move err() to be a class function
This is part of an effort to make it easier for extensions to hook into verify.
author | Durham Goode <durham@fb.com> |
---|---|
date | Fri, 18 Dec 2015 16:42:39 -0800 |
parents | 6b2c1a1871a6 |
children | f4f2179077cb |
comparison
equal
deleted
inserted
replaced
27446:6b2c1a1871a6 | 27447:d1b91c10ce70 |
---|---|
62 | 62 |
63 def warn(self, msg): | 63 def warn(self, msg): |
64 self.ui.warn(msg + "\n") | 64 self.ui.warn(msg + "\n") |
65 self.warnings[0] += 1 | 65 self.warnings[0] += 1 |
66 | 66 |
67 def err(self, linkrev, msg, filename=None): | |
68 if linkrev is not None: | |
69 self.badrevs.add(linkrev) | |
70 else: | |
71 linkrev = '?' | |
72 msg = "%s: %s" % (linkrev, msg) | |
73 if filename: | |
74 msg = "%s@%s" % (filename, msg) | |
75 self.ui.warn(" " + msg + "\n") | |
76 self.errors[0] += 1 | |
77 | |
67 def verify(self): | 78 def verify(self): |
68 repo = self.repo | 79 repo = self.repo |
69 mflinkrevs = {} | 80 mflinkrevs = {} |
70 filelinkrevs = {} | 81 filelinkrevs = {} |
71 filenodes = {} | 82 filenodes = {} |
79 lrugetctx = self.lrugetctx | 90 lrugetctx = self.lrugetctx |
80 | 91 |
81 if not repo.url().startswith('file:'): | 92 if not repo.url().startswith('file:'): |
82 raise error.Abort(_("cannot verify bundle or remote repos")) | 93 raise error.Abort(_("cannot verify bundle or remote repos")) |
83 | 94 |
84 def err(linkrev, msg, filename=None): | |
85 if linkrev is not None: | |
86 badrevs.add(linkrev) | |
87 else: | |
88 linkrev = '?' | |
89 msg = "%s: %s" % (linkrev, msg) | |
90 if filename: | |
91 msg = "%s@%s" % (filename, msg) | |
92 ui.warn(" " + msg + "\n") | |
93 errors[0] += 1 | |
94 | 95 |
95 def exc(linkrev, msg, inst, filename=None): | 96 def exc(linkrev, msg, inst, filename=None): |
96 if isinstance(inst, KeyboardInterrupt): | 97 if isinstance(inst, KeyboardInterrupt): |
97 ui.warn(_("interrupted")) | 98 ui.warn(_("interrupted")) |
98 raise | 99 raise |
99 if not str(inst): | 100 if not str(inst): |
100 inst = repr(inst) | 101 inst = repr(inst) |
101 err(linkrev, "%s: %s" % (msg, inst), filename) | 102 self.err(linkrev, "%s: %s" % (msg, inst), filename) |
102 | 103 |
103 | 104 |
104 def checklog(obj, name, linkrev): | 105 def checklog(obj, name, linkrev): |
105 if not len(obj) and (havecl or havemf): | 106 if not len(obj) and (havecl or havemf): |
106 err(linkrev, _("empty or missing %s") % name) | 107 self.err(linkrev, _("empty or missing %s") % name) |
107 return | 108 return |
108 | 109 |
109 d = obj.checksize() | 110 d = obj.checksize() |
110 if d[0]: | 111 if d[0]: |
111 err(None, _("data length off by %d bytes") % d[0], name) | 112 self.err(None, _("data length off by %d bytes") % d[0], name) |
112 if d[1]: | 113 if d[1]: |
113 err(None, _("index contains %d extra bytes") % d[1], name) | 114 self.err(None, _("index contains %d extra bytes") % d[1], name) |
114 | 115 |
115 if obj.version != revlog.REVLOGV0: | 116 if obj.version != revlog.REVLOGV0: |
116 if not revlogv1: | 117 if not revlogv1: |
117 self.warn(_("warning: `%s' uses revlog format 1") % name) | 118 self.warn(_("warning: `%s' uses revlog format 1") % name) |
118 elif revlogv1: | 119 elif revlogv1: |
123 if lr < 0 or (havecl and lr not in linkrevs): | 124 if lr < 0 or (havecl and lr not in linkrevs): |
124 if lr < 0 or lr >= len(cl): | 125 if lr < 0 or lr >= len(cl): |
125 msg = _("rev %d points to nonexistent changeset %d") | 126 msg = _("rev %d points to nonexistent changeset %d") |
126 else: | 127 else: |
127 msg = _("rev %d points to unexpected changeset %d") | 128 msg = _("rev %d points to unexpected changeset %d") |
128 err(None, msg % (i, lr), f) | 129 self.err(None, msg % (i, lr), f) |
129 if linkrevs: | 130 if linkrevs: |
130 if f and len(linkrevs) > 1: | 131 if f and len(linkrevs) > 1: |
131 try: | 132 try: |
132 # attempt to filter down to real linkrevs | 133 # attempt to filter down to real linkrevs |
133 linkrevs = [l for l in linkrevs | 134 linkrevs = [l for l in linkrevs |
139 lr = None # can't be trusted | 140 lr = None # can't be trusted |
140 | 141 |
141 try: | 142 try: |
142 p1, p2 = obj.parents(node) | 143 p1, p2 = obj.parents(node) |
143 if p1 not in seen and p1 != nullid: | 144 if p1 not in seen and p1 != nullid: |
144 err(lr, _("unknown parent 1 %s of %s") % | 145 self.err(lr, _("unknown parent 1 %s of %s") % |
145 (short(p1), short(node)), f) | 146 (short(p1), short(node)), f) |
146 if p2 not in seen and p2 != nullid: | 147 if p2 not in seen and p2 != nullid: |
147 err(lr, _("unknown parent 2 %s of %s") % | 148 self.err(lr, _("unknown parent 2 %s of %s") % |
148 (short(p2), short(node)), f) | 149 (short(p2), short(node)), f) |
149 except Exception as inst: | 150 except Exception as inst: |
150 exc(lr, _("checking parents of %s") % short(node), inst, f) | 151 exc(lr, _("checking parents of %s") % short(node), inst, f) |
151 | 152 |
152 if node in seen: | 153 if node in seen: |
153 err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f) | 154 self.err(lr, _("duplicate revision %d (%d)") % |
155 (i, seen[node]), f) | |
154 seen[node] = i | 156 seen[node] = i |
155 return lr | 157 return lr |
156 | 158 |
157 if os.path.exists(repo.sjoin("journal")): | 159 if os.path.exists(repo.sjoin("journal")): |
158 ui.warn(_("abandoned transaction found - run hg recover\n")) | 160 ui.warn(_("abandoned transaction found - run hg recover\n")) |
199 n = mf.node(i) | 201 n = mf.node(i) |
200 lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest") | 202 lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest") |
201 if n in mflinkrevs: | 203 if n in mflinkrevs: |
202 del mflinkrevs[n] | 204 del mflinkrevs[n] |
203 else: | 205 else: |
204 err(lr, _("%s not in changesets") % short(n), "manifest") | 206 self.err(lr, _("%s not in changesets") % short(n), "manifest") |
205 | 207 |
206 try: | 208 try: |
207 for f, fn in mf.readdelta(n).iteritems(): | 209 for f, fn in mf.readdelta(n).iteritems(): |
208 if not f: | 210 if not f: |
209 err(lr, _("file without name in manifest")) | 211 self.err(lr, _("file without name in manifest")) |
210 elif f != "/dev/null": # ignore this in very old repos | 212 elif f != "/dev/null": # ignore this in very old repos |
211 if _validpath(repo, f): | 213 if _validpath(repo, f): |
212 filenodes.setdefault( | 214 filenodes.setdefault( |
213 _normpath(f), {}).setdefault(fn, lr) | 215 _normpath(f), {}).setdefault(fn, lr) |
214 except Exception as inst: | 216 except Exception as inst: |
224 for c in mflinkrevs[m]]): | 226 for c in mflinkrevs[m]]): |
225 count += 1 | 227 count += 1 |
226 if m == nullid: | 228 if m == nullid: |
227 continue | 229 continue |
228 ui.progress(_('crosschecking'), count, total=total) | 230 ui.progress(_('crosschecking'), count, total=total) |
229 err(c, _("changeset refers to unknown manifest %s") % short(m)) | 231 self.err(c, _("changeset refers to unknown manifest %s") % |
232 short(m)) | |
230 mflinkrevs = None # del is bad here due to scope issues | 233 mflinkrevs = None # del is bad here due to scope issues |
231 | 234 |
232 for f in sorted(filelinkrevs): | 235 for f in sorted(filelinkrevs): |
233 count += 1 | 236 count += 1 |
234 ui.progress(_('crosschecking'), count, total=total) | 237 ui.progress(_('crosschecking'), count, total=total) |
235 if f not in filenodes: | 238 if f not in filenodes: |
236 lr = filelinkrevs[f][0] | 239 lr = filelinkrevs[f][0] |
237 err(lr, _("in changeset but not in manifest"), f) | 240 self.err(lr, _("in changeset but not in manifest"), f) |
238 | 241 |
239 if havecl: | 242 if havecl: |
240 for f in sorted(filenodes): | 243 for f in sorted(filenodes): |
241 count += 1 | 244 count += 1 |
242 ui.progress(_('crosschecking'), count, total=total) | 245 ui.progress(_('crosschecking'), count, total=total) |
244 try: | 247 try: |
245 fl = repo.file(f) | 248 fl = repo.file(f) |
246 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]]) | 249 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]]) |
247 except Exception: | 250 except Exception: |
248 lr = None | 251 lr = None |
249 err(lr, _("in manifest but not in changeset"), f) | 252 self.err(lr, _("in manifest but not in changeset"), f) |
250 | 253 |
251 ui.progress(_('crosschecking'), None) | 254 ui.progress(_('crosschecking'), None) |
252 | 255 |
253 ui.status(_("checking files\n")) | 256 ui.status(_("checking files\n")) |
254 | 257 |
255 storefiles = set() | 258 storefiles = set() |
256 for f, f2, size in repo.store.datafiles(): | 259 for f, f2, size in repo.store.datafiles(): |
257 if not f: | 260 if not f: |
258 err(None, _("cannot decode filename '%s'") % f2) | 261 self.err(None, _("cannot decode filename '%s'") % f2) |
259 elif size > 0 or not revlogv1: | 262 elif size > 0 or not revlogv1: |
260 storefiles.add(_normpath(f)) | 263 storefiles.add(_normpath(f)) |
261 | 264 |
262 files = sorted(set(filenodes) | set(filelinkrevs)) | 265 files = sorted(set(filenodes) | set(filelinkrevs)) |
263 total = len(files) | 266 total = len(files) |
275 lr = None | 278 lr = None |
276 | 279 |
277 try: | 280 try: |
278 fl = repo.file(f) | 281 fl = repo.file(f) |
279 except error.RevlogError as e: | 282 except error.RevlogError as e: |
280 err(lr, _("broken revlog! (%s)") % e, f) | 283 self.err(lr, _("broken revlog! (%s)") % e, f) |
281 continue | 284 continue |
282 | 285 |
283 for ff in fl.files(): | 286 for ff in fl.files(): |
284 try: | 287 try: |
285 storefiles.remove(ff) | 288 storefiles.remove(ff) |
294 revisions += 1 | 297 revisions += 1 |
295 n = fl.node(i) | 298 n = fl.node(i) |
296 lr = checkentry(fl, i, n, seen, linkrevs, f) | 299 lr = checkentry(fl, i, n, seen, linkrevs, f) |
297 if f in filenodes: | 300 if f in filenodes: |
298 if havemf and n not in filenodes[f]: | 301 if havemf and n not in filenodes[f]: |
299 err(lr, _("%s not in manifests") % (short(n)), f) | 302 self.err(lr, _("%s not in manifests") % (short(n)), f) |
300 else: | 303 else: |
301 del filenodes[f][n] | 304 del filenodes[f][n] |
302 | 305 |
303 # verify contents | 306 # verify contents |
304 try: | 307 try: |
305 l = len(fl.read(n)) | 308 l = len(fl.read(n)) |
306 rp = fl.renamed(n) | 309 rp = fl.renamed(n) |
307 if l != fl.size(i): | 310 if l != fl.size(i): |
308 if len(fl.revision(n)) != fl.size(i): | 311 if len(fl.revision(n)) != fl.size(i): |
309 err(lr, _("unpacked size is %s, %s expected") % | 312 self.err(lr, _("unpacked size is %s, %s expected") % |
310 (l, fl.size(i)), f) | 313 (l, fl.size(i)), f) |
311 except error.CensoredNodeError: | 314 except error.CensoredNodeError: |
312 # experimental config: censor.policy | 315 # experimental config: censor.policy |
313 if ui.config("censor", "policy", "abort") == "abort": | 316 if ui.config("censor", "policy", "abort") == "abort": |
314 err(lr, _("censored file data"), f) | 317 self.err(lr, _("censored file data"), f) |
315 except Exception as inst: | 318 except Exception as inst: |
316 exc(lr, _("unpacking %s") % short(n), inst, f) | 319 exc(lr, _("unpacking %s") % short(n), inst, f) |
317 | 320 |
318 # check renames | 321 # check renames |
319 try: | 322 try: |
328 if not found: | 331 if not found: |
329 self.warn(_("warning: copy source of '%s' not" | 332 self.warn(_("warning: copy source of '%s' not" |
330 " in parents of %s") % (f, ctx)) | 333 " in parents of %s") % (f, ctx)) |
331 fl2 = repo.file(rp[0]) | 334 fl2 = repo.file(rp[0]) |
332 if not len(fl2): | 335 if not len(fl2): |
333 err(lr, _("empty or missing copy source revlog " | 336 self.err(lr, _("empty or missing copy source " |
334 "%s:%s") % (rp[0], short(rp[1])), f) | 337 "revlog %s:%s") % (rp[0], short(rp[1])), f) |
335 elif rp[1] == nullid: | 338 elif rp[1] == nullid: |
336 ui.note(_("warning: %s@%s: copy source" | 339 ui.note(_("warning: %s@%s: copy source" |
337 " revision is nullid %s:%s\n") | 340 " revision is nullid %s:%s\n") |
338 % (f, lr, rp[0], short(rp[1]))) | 341 % (f, lr, rp[0], short(rp[1]))) |
339 else: | 342 else: |
343 | 346 |
344 # cross-check | 347 # cross-check |
345 if f in filenodes: | 348 if f in filenodes: |
346 fns = [(lr, n) for n, lr in filenodes[f].iteritems()] | 349 fns = [(lr, n) for n, lr in filenodes[f].iteritems()] |
347 for lr, node in sorted(fns): | 350 for lr, node in sorted(fns): |
348 err(lr, _("%s in manifests not found") % short(node), f) | 351 self.err(lr, _("%s in manifests not found") % short(node), |
352 f) | |
349 ui.progress(_('checking'), None) | 353 ui.progress(_('checking'), None) |
350 | 354 |
351 for f in storefiles: | 355 for f in storefiles: |
352 self.warn(_("warning: orphan revlog '%s'") % f) | 356 self.warn(_("warning: orphan revlog '%s'") % f) |
353 | 357 |