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] |