comparison mercurial/verify.py @ 27643:62ce86fcfd06

verify: move checkentry() to be a class function This is part of making verify more modular so extensions can hook into it.
author Durham Goode <durham@fb.com>
date Tue, 05 Jan 2016 17:08:14 -0800
parents f6457349985b
children 331e5c28f5f0
comparison
equal deleted inserted replaced
27642:f6457349985b 27643:62ce86fcfd06
95 if not self.revlogv1: 95 if not self.revlogv1:
96 self.warn(_("warning: `%s' uses revlog format 1") % name) 96 self.warn(_("warning: `%s' uses revlog format 1") % name)
97 elif self.revlogv1: 97 elif self.revlogv1:
98 self.warn(_("warning: `%s' uses revlog format 0") % name) 98 self.warn(_("warning: `%s' uses revlog format 0") % name)
99 99
100 def checkentry(self, obj, i, node, seen, linkrevs, f):
101 lr = obj.linkrev(obj.rev(node))
102 if lr < 0 or (self.havecl and lr not in linkrevs):
103 if lr < 0 or lr >= len(self.repo.changelog):
104 msg = _("rev %d points to nonexistent changeset %d")
105 else:
106 msg = _("rev %d points to unexpected changeset %d")
107 self.err(None, msg % (i, lr), f)
108 if linkrevs:
109 if f and len(linkrevs) > 1:
110 try:
111 # attempt to filter down to real linkrevs
112 linkrevs = [l for l in linkrevs
113 if self.lrugetctx(l)[f].filenode() == node]
114 except Exception:
115 pass
116 self.warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
117 lr = None # can't be trusted
118
119 try:
120 p1, p2 = obj.parents(node)
121 if p1 not in seen and p1 != nullid:
122 self.err(lr, _("unknown parent 1 %s of %s") %
123 (short(p1), short(node)), f)
124 if p2 not in seen and p2 != nullid:
125 self.err(lr, _("unknown parent 2 %s of %s") %
126 (short(p2), short(node)), f)
127 except Exception as inst:
128 self.exc(lr, _("checking parents of %s") % short(node), inst, f)
129
130 if node in seen:
131 self.err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
132 seen[node] = i
133 return lr
134
100 def verify(self): 135 def verify(self):
101 repo = self.repo 136 repo = self.repo
102 mflinkrevs = {} 137 mflinkrevs = {}
103 filelinkrevs = {} 138 filelinkrevs = {}
104 filenodes = {} 139 filenodes = {}
110 lrugetctx = self.lrugetctx 145 lrugetctx = self.lrugetctx
111 146
112 if not repo.url().startswith('file:'): 147 if not repo.url().startswith('file:'):
113 raise error.Abort(_("cannot verify bundle or remote repos")) 148 raise error.Abort(_("cannot verify bundle or remote repos"))
114 149
115 def checkentry(obj, i, node, seen, linkrevs, f):
116 lr = obj.linkrev(obj.rev(node))
117 if lr < 0 or (havecl and lr not in linkrevs):
118 if lr < 0 or lr >= len(cl):
119 msg = _("rev %d points to nonexistent changeset %d")
120 else:
121 msg = _("rev %d points to unexpected changeset %d")
122 self.err(None, msg % (i, lr), f)
123 if linkrevs:
124 if f and len(linkrevs) > 1:
125 try:
126 # attempt to filter down to real linkrevs
127 linkrevs = [l for l in linkrevs
128 if lrugetctx(l)[f].filenode() == node]
129 except Exception:
130 pass
131 self.warn(_(" (expected %s)") %
132 " ".join(map(str, linkrevs)))
133 lr = None # can't be trusted
134
135 try:
136 p1, p2 = obj.parents(node)
137 if p1 not in seen and p1 != nullid:
138 self.err(lr, _("unknown parent 1 %s of %s") %
139 (short(p1), short(node)), f)
140 if p2 not in seen and p2 != nullid:
141 self.err(lr, _("unknown parent 2 %s of %s") %
142 (short(p2), short(node)), f)
143 except Exception as inst:
144 self.exc(lr, _("checking parents of %s") % short(node), inst, f)
145
146 if node in seen:
147 self.err(lr, _("duplicate revision %d (%d)") %
148 (i, seen[node]), f)
149 seen[node] = i
150 return lr
151
152 if os.path.exists(repo.sjoin("journal")): 150 if os.path.exists(repo.sjoin("journal")):
153 ui.warn(_("abandoned transaction found - run hg recover\n")) 151 ui.warn(_("abandoned transaction found - run hg recover\n"))
154 152
155 revlogv1 = self.revlogv1 153 revlogv1 = self.revlogv1
156 if ui.verbose or not revlogv1: 154 if ui.verbose or not revlogv1:
165 self.checklog(cl, "changelog", 0) 163 self.checklog(cl, "changelog", 0)
166 total = len(repo) 164 total = len(repo)
167 for i in repo: 165 for i in repo:
168 ui.progress(_('checking'), i, total=total, unit=_('changesets')) 166 ui.progress(_('checking'), i, total=total, unit=_('changesets'))
169 n = cl.node(i) 167 n = cl.node(i)
170 checkentry(cl, i, n, seen, [i], "changelog") 168 self.checkentry(cl, i, n, seen, [i], "changelog")
171 169
172 try: 170 try:
173 changes = cl.read(n) 171 changes = cl.read(n)
174 if changes[0] != nullid: 172 if changes[0] != nullid:
175 mflinkrevs.setdefault(changes[0], []).append(i) 173 mflinkrevs.setdefault(changes[0], []).append(i)
190 self.checklog(mf, "manifest", 0) 188 self.checklog(mf, "manifest", 0)
191 total = len(mf) 189 total = len(mf)
192 for i in mf: 190 for i in mf:
193 ui.progress(_('checking'), i, total=total, unit=_('manifests')) 191 ui.progress(_('checking'), i, total=total, unit=_('manifests'))
194 n = mf.node(i) 192 n = mf.node(i)
195 lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest") 193 lr = self.checkentry(mf, i, n, seen, mflinkrevs.get(n, []),
194 "manifest")
196 if n in mflinkrevs: 195 if n in mflinkrevs:
197 del mflinkrevs[n] 196 del mflinkrevs[n]
198 else: 197 else:
199 self.err(lr, _("%s not in changesets") % short(n), "manifest") 198 self.err(lr, _("%s not in changesets") % short(n), "manifest")
200 199
287 seen = {} 286 seen = {}
288 rp = None 287 rp = None
289 for i in fl: 288 for i in fl:
290 revisions += 1 289 revisions += 1
291 n = fl.node(i) 290 n = fl.node(i)
292 lr = checkentry(fl, i, n, seen, linkrevs, f) 291 lr = self.checkentry(fl, i, n, seen, linkrevs, f)
293 if f in filenodes: 292 if f in filenodes:
294 if havemf and n not in filenodes[f]: 293 if havemf and n not in filenodes[f]:
295 self.err(lr, _("%s not in manifests") % (short(n)), f) 294 self.err(lr, _("%s not in manifests") % (short(n)), f)
296 else: 295 else:
297 del filenodes[f][n] 296 del filenodes[f][n]