##// END OF EJS Templates
verify: drop unnecessary check for nullid...
Martin von Zweigbergk -
r28112:334a3aa6 default
parent child Browse files
Show More
@@ -1,383 +1,381 b''
1 # verify.py - repository integrity checking for Mercurial
1 # verify.py - repository integrity checking for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11
11
12 from .i18n import _
12 from .i18n import _
13 from .node import (
13 from .node import (
14 nullid,
14 nullid,
15 short,
15 short,
16 )
16 )
17
17
18 from . import (
18 from . import (
19 error,
19 error,
20 revlog,
20 revlog,
21 util,
21 util,
22 )
22 )
23
23
24 def verify(repo):
24 def verify(repo):
25 with repo.lock():
25 with repo.lock():
26 return verifier(repo).verify()
26 return verifier(repo).verify()
27
27
28 def _normpath(f):
28 def _normpath(f):
29 # under hg < 2.4, convert didn't sanitize paths properly, so a
29 # under hg < 2.4, convert didn't sanitize paths properly, so a
30 # converted repo may contain repeated slashes
30 # converted repo may contain repeated slashes
31 while '//' in f:
31 while '//' in f:
32 f = f.replace('//', '/')
32 f = f.replace('//', '/')
33 return f
33 return f
34
34
35 def _validpath(repo, path):
35 def _validpath(repo, path):
36 """Returns False if a path should NOT be treated as part of a repo.
36 """Returns False if a path should NOT be treated as part of a repo.
37
37
38 For all in-core cases, this returns True, as we have no way for a
38 For all in-core cases, this returns True, as we have no way for a
39 path to be mentioned in the history but not actually be
39 path to be mentioned in the history but not actually be
40 relevant. For narrow clones, this is important because many
40 relevant. For narrow clones, this is important because many
41 filelogs will be missing, and changelog entries may mention
41 filelogs will be missing, and changelog entries may mention
42 modified files that are outside the narrow scope.
42 modified files that are outside the narrow scope.
43 """
43 """
44 return True
44 return True
45
45
46 class verifier(object):
46 class verifier(object):
47 def __init__(self, repo):
47 def __init__(self, repo):
48 self.repo = repo.unfiltered()
48 self.repo = repo.unfiltered()
49 self.ui = repo.ui
49 self.ui = repo.ui
50 self.badrevs = set()
50 self.badrevs = set()
51 self.errors = 0
51 self.errors = 0
52 self.warnings = 0
52 self.warnings = 0
53 self.havecl = len(repo.changelog) > 0
53 self.havecl = len(repo.changelog) > 0
54 self.havemf = len(repo.manifest) > 0
54 self.havemf = len(repo.manifest) > 0
55 self.revlogv1 = repo.changelog.version != revlog.REVLOGV0
55 self.revlogv1 = repo.changelog.version != revlog.REVLOGV0
56 self.lrugetctx = util.lrucachefunc(repo.changectx)
56 self.lrugetctx = util.lrucachefunc(repo.changectx)
57 self.refersmf = False
57 self.refersmf = False
58 self.fncachewarned = False
58 self.fncachewarned = False
59
59
60 def warn(self, msg):
60 def warn(self, msg):
61 self.ui.warn(msg + "\n")
61 self.ui.warn(msg + "\n")
62 self.warnings += 1
62 self.warnings += 1
63
63
64 def err(self, linkrev, msg, filename=None):
64 def err(self, linkrev, msg, filename=None):
65 if linkrev is not None:
65 if linkrev is not None:
66 self.badrevs.add(linkrev)
66 self.badrevs.add(linkrev)
67 else:
67 else:
68 linkrev = '?'
68 linkrev = '?'
69 msg = "%s: %s" % (linkrev, msg)
69 msg = "%s: %s" % (linkrev, msg)
70 if filename:
70 if filename:
71 msg = "%s@%s" % (filename, msg)
71 msg = "%s@%s" % (filename, msg)
72 self.ui.warn(" " + msg + "\n")
72 self.ui.warn(" " + msg + "\n")
73 self.errors += 1
73 self.errors += 1
74
74
75 def exc(self, linkrev, msg, inst, filename=None):
75 def exc(self, linkrev, msg, inst, filename=None):
76 if not str(inst):
76 if not str(inst):
77 inst = repr(inst)
77 inst = repr(inst)
78 self.err(linkrev, "%s: %s" % (msg, inst), filename)
78 self.err(linkrev, "%s: %s" % (msg, inst), filename)
79
79
80 def checklog(self, obj, name, linkrev):
80 def checklog(self, obj, name, linkrev):
81 if not len(obj) and (self.havecl or self.havemf):
81 if not len(obj) and (self.havecl or self.havemf):
82 self.err(linkrev, _("empty or missing %s") % name)
82 self.err(linkrev, _("empty or missing %s") % name)
83 return
83 return
84
84
85 d = obj.checksize()
85 d = obj.checksize()
86 if d[0]:
86 if d[0]:
87 self.err(None, _("data length off by %d bytes") % d[0], name)
87 self.err(None, _("data length off by %d bytes") % d[0], name)
88 if d[1]:
88 if d[1]:
89 self.err(None, _("index contains %d extra bytes") % d[1], name)
89 self.err(None, _("index contains %d extra bytes") % d[1], name)
90
90
91 if obj.version != revlog.REVLOGV0:
91 if obj.version != revlog.REVLOGV0:
92 if not self.revlogv1:
92 if not self.revlogv1:
93 self.warn(_("warning: `%s' uses revlog format 1") % name)
93 self.warn(_("warning: `%s' uses revlog format 1") % name)
94 elif self.revlogv1:
94 elif self.revlogv1:
95 self.warn(_("warning: `%s' uses revlog format 0") % name)
95 self.warn(_("warning: `%s' uses revlog format 0") % name)
96
96
97 def checkentry(self, obj, i, node, seen, linkrevs, f):
97 def checkentry(self, obj, i, node, seen, linkrevs, f):
98 lr = obj.linkrev(obj.rev(node))
98 lr = obj.linkrev(obj.rev(node))
99 if lr < 0 or (self.havecl and lr not in linkrevs):
99 if lr < 0 or (self.havecl and lr not in linkrevs):
100 if lr < 0 or lr >= len(self.repo.changelog):
100 if lr < 0 or lr >= len(self.repo.changelog):
101 msg = _("rev %d points to nonexistent changeset %d")
101 msg = _("rev %d points to nonexistent changeset %d")
102 else:
102 else:
103 msg = _("rev %d points to unexpected changeset %d")
103 msg = _("rev %d points to unexpected changeset %d")
104 self.err(None, msg % (i, lr), f)
104 self.err(None, msg % (i, lr), f)
105 if linkrevs:
105 if linkrevs:
106 if f and len(linkrevs) > 1:
106 if f and len(linkrevs) > 1:
107 try:
107 try:
108 # attempt to filter down to real linkrevs
108 # attempt to filter down to real linkrevs
109 linkrevs = [l for l in linkrevs
109 linkrevs = [l for l in linkrevs
110 if self.lrugetctx(l)[f].filenode() == node]
110 if self.lrugetctx(l)[f].filenode() == node]
111 except Exception:
111 except Exception:
112 pass
112 pass
113 self.warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
113 self.warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
114 lr = None # can't be trusted
114 lr = None # can't be trusted
115
115
116 try:
116 try:
117 p1, p2 = obj.parents(node)
117 p1, p2 = obj.parents(node)
118 if p1 not in seen and p1 != nullid:
118 if p1 not in seen and p1 != nullid:
119 self.err(lr, _("unknown parent 1 %s of %s") %
119 self.err(lr, _("unknown parent 1 %s of %s") %
120 (short(p1), short(node)), f)
120 (short(p1), short(node)), f)
121 if p2 not in seen and p2 != nullid:
121 if p2 not in seen and p2 != nullid:
122 self.err(lr, _("unknown parent 2 %s of %s") %
122 self.err(lr, _("unknown parent 2 %s of %s") %
123 (short(p2), short(node)), f)
123 (short(p2), short(node)), f)
124 except Exception as inst:
124 except Exception as inst:
125 self.exc(lr, _("checking parents of %s") % short(node), inst, f)
125 self.exc(lr, _("checking parents of %s") % short(node), inst, f)
126
126
127 if node in seen:
127 if node in seen:
128 self.err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
128 self.err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
129 seen[node] = i
129 seen[node] = i
130 return lr
130 return lr
131
131
132 def verify(self):
132 def verify(self):
133 repo = self.repo
133 repo = self.repo
134
134
135 ui = repo.ui
135 ui = repo.ui
136
136
137 if not repo.url().startswith('file:'):
137 if not repo.url().startswith('file:'):
138 raise error.Abort(_("cannot verify bundle or remote repos"))
138 raise error.Abort(_("cannot verify bundle or remote repos"))
139
139
140 if os.path.exists(repo.sjoin("journal")):
140 if os.path.exists(repo.sjoin("journal")):
141 ui.warn(_("abandoned transaction found - run hg recover\n"))
141 ui.warn(_("abandoned transaction found - run hg recover\n"))
142
142
143 if ui.verbose or not self.revlogv1:
143 if ui.verbose or not self.revlogv1:
144 ui.status(_("repository uses revlog format %d\n") %
144 ui.status(_("repository uses revlog format %d\n") %
145 (self.revlogv1 and 1 or 0))
145 (self.revlogv1 and 1 or 0))
146
146
147 mflinkrevs, filelinkrevs = self._verifychangelog()
147 mflinkrevs, filelinkrevs = self._verifychangelog()
148
148
149 filenodes = self._verifymanifest(mflinkrevs)
149 filenodes = self._verifymanifest(mflinkrevs)
150 del mflinkrevs
150 del mflinkrevs
151
151
152 self._crosscheckfiles(filelinkrevs, filenodes)
152 self._crosscheckfiles(filelinkrevs, filenodes)
153
153
154 totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs)
154 totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs)
155
155
156 ui.status(_("%d files, %d changesets, %d total revisions\n") %
156 ui.status(_("%d files, %d changesets, %d total revisions\n") %
157 (totalfiles, len(repo.changelog), filerevisions))
157 (totalfiles, len(repo.changelog), filerevisions))
158 if self.warnings:
158 if self.warnings:
159 ui.warn(_("%d warnings encountered!\n") % self.warnings)
159 ui.warn(_("%d warnings encountered!\n") % self.warnings)
160 if self.fncachewarned:
160 if self.fncachewarned:
161 ui.warn(_('hint: run "hg debugrebuildfncache" to recover from '
161 ui.warn(_('hint: run "hg debugrebuildfncache" to recover from '
162 'corrupt fncache\n'))
162 'corrupt fncache\n'))
163 if self.errors:
163 if self.errors:
164 ui.warn(_("%d integrity errors encountered!\n") % self.errors)
164 ui.warn(_("%d integrity errors encountered!\n") % self.errors)
165 if self.badrevs:
165 if self.badrevs:
166 ui.warn(_("(first damaged changeset appears to be %d)\n")
166 ui.warn(_("(first damaged changeset appears to be %d)\n")
167 % min(self.badrevs))
167 % min(self.badrevs))
168 return 1
168 return 1
169
169
170 def _verifychangelog(self):
170 def _verifychangelog(self):
171 ui = self.ui
171 ui = self.ui
172 repo = self.repo
172 repo = self.repo
173 cl = repo.changelog
173 cl = repo.changelog
174
174
175 ui.status(_("checking changesets\n"))
175 ui.status(_("checking changesets\n"))
176 mflinkrevs = {}
176 mflinkrevs = {}
177 filelinkrevs = {}
177 filelinkrevs = {}
178 seen = {}
178 seen = {}
179 self.checklog(cl, "changelog", 0)
179 self.checklog(cl, "changelog", 0)
180 total = len(repo)
180 total = len(repo)
181 for i in repo:
181 for i in repo:
182 ui.progress(_('checking'), i, total=total, unit=_('changesets'))
182 ui.progress(_('checking'), i, total=total, unit=_('changesets'))
183 n = cl.node(i)
183 n = cl.node(i)
184 self.checkentry(cl, i, n, seen, [i], "changelog")
184 self.checkentry(cl, i, n, seen, [i], "changelog")
185
185
186 try:
186 try:
187 changes = cl.read(n)
187 changes = cl.read(n)
188 if changes[0] != nullid:
188 if changes[0] != nullid:
189 mflinkrevs.setdefault(changes[0], []).append(i)
189 mflinkrevs.setdefault(changes[0], []).append(i)
190 self.refersmf = True
190 self.refersmf = True
191 for f in changes[3]:
191 for f in changes[3]:
192 if _validpath(repo, f):
192 if _validpath(repo, f):
193 filelinkrevs.setdefault(_normpath(f), []).append(i)
193 filelinkrevs.setdefault(_normpath(f), []).append(i)
194 except Exception as inst:
194 except Exception as inst:
195 self.refersmf = True
195 self.refersmf = True
196 self.exc(i, _("unpacking changeset %s") % short(n), inst)
196 self.exc(i, _("unpacking changeset %s") % short(n), inst)
197 ui.progress(_('checking'), None)
197 ui.progress(_('checking'), None)
198 return mflinkrevs, filelinkrevs
198 return mflinkrevs, filelinkrevs
199
199
200 def _verifymanifest(self, mflinkrevs):
200 def _verifymanifest(self, mflinkrevs):
201 repo = self.repo
201 repo = self.repo
202 ui = self.ui
202 ui = self.ui
203 mf = self.repo.manifest
203 mf = self.repo.manifest
204
204
205 ui.status(_("checking manifests\n"))
205 ui.status(_("checking manifests\n"))
206 filenodes = {}
206 filenodes = {}
207 seen = {}
207 seen = {}
208 if self.refersmf:
208 if self.refersmf:
209 # Do not check manifest if there are only changelog entries with
209 # Do not check manifest if there are only changelog entries with
210 # null manifests.
210 # null manifests.
211 self.checklog(mf, "manifest", 0)
211 self.checklog(mf, "manifest", 0)
212 total = len(mf)
212 total = len(mf)
213 for i in mf:
213 for i in mf:
214 ui.progress(_('checking'), i, total=total, unit=_('manifests'))
214 ui.progress(_('checking'), i, total=total, unit=_('manifests'))
215 n = mf.node(i)
215 n = mf.node(i)
216 lr = self.checkentry(mf, i, n, seen, mflinkrevs.get(n, []),
216 lr = self.checkentry(mf, i, n, seen, mflinkrevs.get(n, []),
217 "manifest")
217 "manifest")
218 if n in mflinkrevs:
218 if n in mflinkrevs:
219 del mflinkrevs[n]
219 del mflinkrevs[n]
220 else:
220 else:
221 self.err(lr, _("%s not in changesets") % short(n), "manifest")
221 self.err(lr, _("%s not in changesets") % short(n), "manifest")
222
222
223 try:
223 try:
224 for f, fn in mf.readdelta(n).iteritems():
224 for f, fn in mf.readdelta(n).iteritems():
225 if not f:
225 if not f:
226 self.err(lr, _("file without name in manifest"))
226 self.err(lr, _("file without name in manifest"))
227 elif f != "/dev/null": # ignore this in very old repos
227 elif f != "/dev/null": # ignore this in very old repos
228 if _validpath(repo, f):
228 if _validpath(repo, f):
229 filenodes.setdefault(
229 filenodes.setdefault(
230 _normpath(f), {}).setdefault(fn, lr)
230 _normpath(f), {}).setdefault(fn, lr)
231 except Exception as inst:
231 except Exception as inst:
232 self.exc(lr, _("reading manifest delta %s") % short(n), inst)
232 self.exc(lr, _("reading manifest delta %s") % short(n), inst)
233 ui.progress(_('checking'), None)
233 ui.progress(_('checking'), None)
234
234
235 if self.havemf:
235 if self.havemf:
236 for c, m in sorted([(c, m) for m in mflinkrevs
236 for c, m in sorted([(c, m) for m in mflinkrevs
237 for c in mflinkrevs[m]]):
237 for c in mflinkrevs[m]]):
238 if m == nullid:
239 continue
240 self.err(c, _("changeset refers to unknown manifest %s") %
238 self.err(c, _("changeset refers to unknown manifest %s") %
241 short(m))
239 short(m))
242
240
243 return filenodes
241 return filenodes
244
242
245 def _crosscheckfiles(self, filelinkrevs, filenodes):
243 def _crosscheckfiles(self, filelinkrevs, filenodes):
246 repo = self.repo
244 repo = self.repo
247 ui = self.ui
245 ui = self.ui
248 ui.status(_("crosschecking files in changesets and manifests\n"))
246 ui.status(_("crosschecking files in changesets and manifests\n"))
249
247
250 total = len(filelinkrevs) + len(filenodes)
248 total = len(filelinkrevs) + len(filenodes)
251 count = 0
249 count = 0
252 if self.havemf:
250 if self.havemf:
253 for f in sorted(filelinkrevs):
251 for f in sorted(filelinkrevs):
254 count += 1
252 count += 1
255 ui.progress(_('crosschecking'), count, total=total)
253 ui.progress(_('crosschecking'), count, total=total)
256 if f not in filenodes:
254 if f not in filenodes:
257 lr = filelinkrevs[f][0]
255 lr = filelinkrevs[f][0]
258 self.err(lr, _("in changeset but not in manifest"), f)
256 self.err(lr, _("in changeset but not in manifest"), f)
259
257
260 if self.havecl:
258 if self.havecl:
261 for f in sorted(filenodes):
259 for f in sorted(filenodes):
262 count += 1
260 count += 1
263 ui.progress(_('crosschecking'), count, total=total)
261 ui.progress(_('crosschecking'), count, total=total)
264 if f not in filelinkrevs:
262 if f not in filelinkrevs:
265 try:
263 try:
266 fl = repo.file(f)
264 fl = repo.file(f)
267 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
265 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
268 except Exception:
266 except Exception:
269 lr = None
267 lr = None
270 self.err(lr, _("in manifest but not in changeset"), f)
268 self.err(lr, _("in manifest but not in changeset"), f)
271
269
272 ui.progress(_('crosschecking'), None)
270 ui.progress(_('crosschecking'), None)
273
271
274 def _verifyfiles(self, filenodes, filelinkrevs):
272 def _verifyfiles(self, filenodes, filelinkrevs):
275 repo = self.repo
273 repo = self.repo
276 ui = self.ui
274 ui = self.ui
277 lrugetctx = self.lrugetctx
275 lrugetctx = self.lrugetctx
278 revlogv1 = self.revlogv1
276 revlogv1 = self.revlogv1
279 havemf = self.havemf
277 havemf = self.havemf
280 ui.status(_("checking files\n"))
278 ui.status(_("checking files\n"))
281
279
282 storefiles = set()
280 storefiles = set()
283 for f, f2, size in repo.store.datafiles():
281 for f, f2, size in repo.store.datafiles():
284 if not f:
282 if not f:
285 self.err(None, _("cannot decode filename '%s'") % f2)
283 self.err(None, _("cannot decode filename '%s'") % f2)
286 elif (size > 0 or not revlogv1) and f.startswith('data/'):
284 elif (size > 0 or not revlogv1) and f.startswith('data/'):
287 storefiles.add(_normpath(f))
285 storefiles.add(_normpath(f))
288
286
289 files = sorted(set(filenodes) | set(filelinkrevs))
287 files = sorted(set(filenodes) | set(filelinkrevs))
290 total = len(files)
288 total = len(files)
291 revisions = 0
289 revisions = 0
292 for i, f in enumerate(files):
290 for i, f in enumerate(files):
293 ui.progress(_('checking'), i, item=f, total=total)
291 ui.progress(_('checking'), i, item=f, total=total)
294 try:
292 try:
295 linkrevs = filelinkrevs[f]
293 linkrevs = filelinkrevs[f]
296 except KeyError:
294 except KeyError:
297 # in manifest but not in changelog
295 # in manifest but not in changelog
298 linkrevs = []
296 linkrevs = []
299
297
300 if linkrevs:
298 if linkrevs:
301 lr = linkrevs[0]
299 lr = linkrevs[0]
302 else:
300 else:
303 lr = None
301 lr = None
304
302
305 try:
303 try:
306 fl = repo.file(f)
304 fl = repo.file(f)
307 except error.RevlogError as e:
305 except error.RevlogError as e:
308 self.err(lr, _("broken revlog! (%s)") % e, f)
306 self.err(lr, _("broken revlog! (%s)") % e, f)
309 continue
307 continue
310
308
311 for ff in fl.files():
309 for ff in fl.files():
312 try:
310 try:
313 storefiles.remove(ff)
311 storefiles.remove(ff)
314 except KeyError:
312 except KeyError:
315 self.warn(_(" warning: revlog '%s' not in fncache!") % ff)
313 self.warn(_(" warning: revlog '%s' not in fncache!") % ff)
316 self.fncachewarned = True
314 self.fncachewarned = True
317
315
318 self.checklog(fl, f, lr)
316 self.checklog(fl, f, lr)
319 seen = {}
317 seen = {}
320 rp = None
318 rp = None
321 for i in fl:
319 for i in fl:
322 revisions += 1
320 revisions += 1
323 n = fl.node(i)
321 n = fl.node(i)
324 lr = self.checkentry(fl, i, n, seen, linkrevs, f)
322 lr = self.checkentry(fl, i, n, seen, linkrevs, f)
325 if f in filenodes:
323 if f in filenodes:
326 if havemf and n not in filenodes[f]:
324 if havemf and n not in filenodes[f]:
327 self.err(lr, _("%s not in manifests") % (short(n)), f)
325 self.err(lr, _("%s not in manifests") % (short(n)), f)
328 else:
326 else:
329 del filenodes[f][n]
327 del filenodes[f][n]
330
328
331 # verify contents
329 # verify contents
332 try:
330 try:
333 l = len(fl.read(n))
331 l = len(fl.read(n))
334 rp = fl.renamed(n)
332 rp = fl.renamed(n)
335 if l != fl.size(i):
333 if l != fl.size(i):
336 if len(fl.revision(n)) != fl.size(i):
334 if len(fl.revision(n)) != fl.size(i):
337 self.err(lr, _("unpacked size is %s, %s expected") %
335 self.err(lr, _("unpacked size is %s, %s expected") %
338 (l, fl.size(i)), f)
336 (l, fl.size(i)), f)
339 except error.CensoredNodeError:
337 except error.CensoredNodeError:
340 # experimental config: censor.policy
338 # experimental config: censor.policy
341 if ui.config("censor", "policy", "abort") == "abort":
339 if ui.config("censor", "policy", "abort") == "abort":
342 self.err(lr, _("censored file data"), f)
340 self.err(lr, _("censored file data"), f)
343 except Exception as inst:
341 except Exception as inst:
344 self.exc(lr, _("unpacking %s") % short(n), inst, f)
342 self.exc(lr, _("unpacking %s") % short(n), inst, f)
345
343
346 # check renames
344 # check renames
347 try:
345 try:
348 if rp:
346 if rp:
349 if lr is not None and ui.verbose:
347 if lr is not None and ui.verbose:
350 ctx = lrugetctx(lr)
348 ctx = lrugetctx(lr)
351 found = False
349 found = False
352 for pctx in ctx.parents():
350 for pctx in ctx.parents():
353 if rp[0] in pctx:
351 if rp[0] in pctx:
354 found = True
352 found = True
355 break
353 break
356 if not found:
354 if not found:
357 self.warn(_("warning: copy source of '%s' not"
355 self.warn(_("warning: copy source of '%s' not"
358 " in parents of %s") % (f, ctx))
356 " in parents of %s") % (f, ctx))
359 fl2 = repo.file(rp[0])
357 fl2 = repo.file(rp[0])
360 if not len(fl2):
358 if not len(fl2):
361 self.err(lr, _("empty or missing copy source "
359 self.err(lr, _("empty or missing copy source "
362 "revlog %s:%s") % (rp[0], short(rp[1])), f)
360 "revlog %s:%s") % (rp[0], short(rp[1])), f)
363 elif rp[1] == nullid:
361 elif rp[1] == nullid:
364 ui.note(_("warning: %s@%s: copy source"
362 ui.note(_("warning: %s@%s: copy source"
365 " revision is nullid %s:%s\n")
363 " revision is nullid %s:%s\n")
366 % (f, lr, rp[0], short(rp[1])))
364 % (f, lr, rp[0], short(rp[1])))
367 else:
365 else:
368 fl2.rev(rp[1])
366 fl2.rev(rp[1])
369 except Exception as inst:
367 except Exception as inst:
370 self.exc(lr, _("checking rename of %s") % short(n), inst, f)
368 self.exc(lr, _("checking rename of %s") % short(n), inst, f)
371
369
372 # cross-check
370 # cross-check
373 if f in filenodes:
371 if f in filenodes:
374 fns = [(lr, n) for n, lr in filenodes[f].iteritems()]
372 fns = [(lr, n) for n, lr in filenodes[f].iteritems()]
375 for lr, node in sorted(fns):
373 for lr, node in sorted(fns):
376 self.err(lr, _("%s in manifests not found") % short(node),
374 self.err(lr, _("%s in manifests not found") % short(node),
377 f)
375 f)
378 ui.progress(_('checking'), None)
376 ui.progress(_('checking'), None)
379
377
380 for f in storefiles:
378 for f in storefiles:
381 self.warn(_("warning: orphan revlog '%s'") % f)
379 self.warn(_("warning: orphan revlog '%s'") % f)
382
380
383 return len(files), revisions
381 return len(files), revisions
General Comments 0
You need to be logged in to leave comments. Login now