# HG changeset patch # User Matt Mackall # Date 1190655266 18000 # Node ID 5971cfc0a56a9ff9b324c8fa32f77b9ba21b0423 # Parent 7b4b874ce12ca0ca3f823cac8e6d2d4ef6cd8c6b# Parent 8409a2e3a78dfbe2f6b791792f55381c746a728e Merge with crew diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -803,7 +803,10 @@ def debugindex(ui, file_): " nodeid p1 p2\n") for i in xrange(r.count()): node = r.node(i) - pp = r.parents(node) + try: + pp = r.parents(node) + except: + pp = [nullid, nullid] ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % ( i, r.start(i), r.length(i), r.base(i), r.linkrev(node), short(node), short(pp[0]), short(pp[1]))) diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -912,7 +912,8 @@ class revlog(object): # check rev flags if self.index[rev][0] & 0xFFFF: - raise RevlogError(_('incompatible revision flag %x') % q) + raise RevlogError(_('incompatible revision flag %x') % + (self.index[rev][0] & 0xFFFF)) if self._inline: # we probably have the whole chunk cached @@ -1236,7 +1237,7 @@ class revlog(object): def checksize(self): expected = 0 if self.count(): - expected = self.end(self.count() - 1) + expected = max(0, self.end(self.count() - 1)) try: f = self.opener(self.datafile) @@ -1253,12 +1254,12 @@ class revlog(object): f.seek(0, 2) actual = f.tell() s = self._io.size - i = actual / s + i = max(0, actual / s) di = actual - (i * s) if self._inline: databytes = 0 for r in xrange(self.count()): - databytes += self.length(r) + databytes += max(0, self.length(r)) dd = 0 di = actual - self.count() * s - databytes except IOError, inst: diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -20,12 +20,23 @@ def _verify(repo): filelinkrevs = {} filenodes = {} changesets = revisions = files = 0 + firstbad = [None] errors = [0] warnings = [0] neededmanifests = {} - def err(msg): - repo.ui.warn(msg + "\n") + def err(linkrev, msg, filename=None): + if linkrev != None: + if firstbad[0] != None: + firstbad[0] = min(firstbad[0], linkrev) + else: + firstbad[0] = linkrev + else: + linkrev = "?" + msg = "%s: %s" % (linkrev, msg) + if filename: + msg = "%s@%s" % (filename, msg) + repo.ui.warn(" " + msg + "\n") errors[0] += 1 def warn(msg): @@ -35,9 +46,9 @@ def _verify(repo): def checksize(obj, name): d = obj.checksize() if d[0]: - err(_("%s data length off by %d bytes") % (name, d[0])) + err(None, _("data length off by %d bytes") % d[0], name) if d[1]: - err(_("%s index contains %d extra bytes") % (name, d[1])) + err(None, _("index contains %d extra bytes") % d[1], name) def checkversion(obj, name): if obj.version != revlog.REVLOGV0: @@ -60,25 +71,25 @@ def _verify(repo): n = repo.changelog.node(i) l = repo.changelog.linkrev(n) if l != i: - err(_("incorrect link (%d) for changeset revision %d") %(l, i)) + err(i, _("incorrect link (%d) for changeset") %(l)) if n in seen: - err(_("duplicate changeset at revision %d") % i) - seen[n] = 1 + err(i, _("duplicates changeset at revision %d") % seen[n]) + seen[n] = i for p in repo.changelog.parents(n): if p not in repo.changelog.nodemap: - err(_("changeset %s has unknown parent %s") % - (short(n), short(p))) + err(i, _("changeset has unknown parent %s") % short(p)) try: changes = repo.changelog.read(n) except KeyboardInterrupt: repo.ui.warn(_("interrupted")) raise except Exception, inst: - err(_("unpacking changeset %s: %s") % (short(n), inst)) + err(i, _("unpacking changeset: %s") % inst) continue - neededmanifests[changes[0]] = n + if changes[0] not in neededmanifests: + neededmanifests[changes[0]] = i for f in changes[3]: filelinkrevs.setdefault(f, []).append(i) @@ -93,45 +104,50 @@ def _verify(repo): l = repo.manifest.linkrev(n) if l < 0 or l >= repo.changelog.count(): - err(_("bad manifest link (%d) at revision %d") % (l, i)) + err(None, _("bad link (%d) at manifest revision %d") % (l, i)) if n in neededmanifests: del neededmanifests[n] if n in seen: - err(_("duplicate manifest at revision %d") % i) + err(l, _("duplicates manifest from %d") % seen[n]) - seen[n] = 1 + seen[n] = l for p in repo.manifest.parents(n): if p not in repo.manifest.nodemap: - err(_("manifest %s has unknown parent %s") % - (short(n), short(p))) + err(l, _("manifest has unknown parent %s") % short(p)) try: for f, fn in repo.manifest.readdelta(n).iteritems(): - filenodes.setdefault(f, {})[fn] = 1 + fns = filenodes.setdefault(f, {}) + if fn not in fns: + fns[fn] = n except KeyboardInterrupt: repo.ui.warn(_("interrupted")) raise except Exception, inst: - err(_("reading delta for manifest %s: %s") % (short(n), inst)) + err(l, _("reading manifest delta: %s") % inst) continue repo.ui.status(_("crosschecking files in changesets and manifests\n")) - for m, c in neededmanifests.items(): - err(_("Changeset %s refers to unknown manifest %s") % - (short(m), short(c))) - del neededmanifests + nm = neededmanifests.items() + nm.sort() + for m, c in nm: + err(m, _("changeset refers to unknown manifest %s") % short(c)) + del neededmanifests, nm for f in filenodes: if f not in filelinkrevs: - err(_("file %s in manifest but not in changesets") % f) + lrs = [repo.manifest.linkrev(n) for n in filenodes[f]] + lrs.sort() + err(lrs[0], _("in manifest but not in changeset"), f) for f in filelinkrevs: if f not in filenodes: - err(_("file %s in changeset but not in manifest") % f) + lr = filelinkrevs[f][0] + err(lr, _("in changeset but not in manifest"), f) repo.ui.status(_("checking files\n")) ff = filenodes.keys() @@ -141,33 +157,40 @@ def _verify(repo): continue files += 1 if not f: - err(_("file without name in manifest %s") % short(n)) + lr = repo.manifest.linkrev(filenodes[f][0]) + err(lr, _("file without name in manifest %s") % short(ff[n])) continue fl = repo.file(f) checkversion(fl, f) checksize(fl, f) + seen = {} nodes = {nullid: 1} - seen = {} for i in xrange(fl.count()): revisions += 1 n = fl.node(i) + flr = fl.linkrev(n) + + if flr not in filelinkrevs.get(f, []): + if flr < 0 or flr >= repo.changelog.count(): + err(None, _("rev %d point to nonexistent changeset %d") + % (i, flr), f) + else: + err(None, _("rev %d points to unexpected changeset %d") + % (i, flr), f) + if f in filelinkrevs: + warn(_(" (expected %s)") % filelinkrevs[f][0]) + flr = None # can't be trusted + else: + filelinkrevs[f].remove(flr) if n in seen: - err(_("%s: duplicate revision %d") % (f, i)) + err(flr, _("duplicate revision %d") % i, f) if n not in filenodes[f]: - err(_("%s: %d:%s not in manifests") % (f, i, short(n))) + err(flr, _("%s not in manifests") % (short(n)), f) else: del filenodes[f][n] - flr = fl.linkrev(n) - if flr not in filelinkrevs.get(f, []): - err(_("%s:%s points to unexpected changeset %d") - % (f, short(n), flr)) - err(_("expecting one of %s" % filelinkrevs.get(f, []))) - else: - filelinkrevs[f].remove(flr) - # verify contents try: t = fl.read(n) @@ -175,16 +198,22 @@ def _verify(repo): repo.ui.warn(_("interrupted")) raise except Exception, inst: - err(_("unpacking file %s %s: %s") % (f, short(n), inst)) + err(flr, _("unpacking %s: %s") % (short(n), inst), f) # verify parents - (p1, p2) = fl.parents(n) - if p1 not in nodes: - err(_("file %s:%s unknown parent 1 %s") % - (f, short(n), short(p1))) - if p2 not in nodes: - err(_("file %s:%s unknown parent 2 %s") % - (f, short(n), short(p1))) + try: + (p1, p2) = fl.parents(n) + if p1 not in nodes: + err(flr, _("unknown parent 1 %s of %s") % + (short(p1), short(n)), f) + if p2 not in nodes: + err(flr, _("unknown parent 2 %s of %s") % + (short(p2), short(p1)), f) + except KeyboardInterrupt: + repo.ui.warn(_("interrupted")) + raise + except Exception, inst: + err(flr, _("checking parents of %s: %s") % (short(n), inst), f) nodes[n] = 1 # check renames @@ -197,11 +226,15 @@ def _verify(repo): repo.ui.warn(_("interrupted")) raise except Exception, inst: - err(_("checking rename on file %s %s: %s") % (f, short(n), inst)) + err(flr, _("checking rename of %s: %s") % + (short(n), inst), f) # cross-check - for node in filenodes[f]: - err(_("node %s in manifests not in %s") % (hex(node), f)) + fns = [(repo.manifest.linkrev(filenodes[f][n]), n) + for n in filenodes[f]] + fns.sort() + for lr, node in fns: + err(lr, _("%s in manifests not found") % short(node), f) repo.ui.status(_("%d files, %d changesets, %d total revisions\n") % (files, changesets, revisions)) @@ -210,5 +243,8 @@ def _verify(repo): repo.ui.warn(_("%d warnings encountered!\n") % warnings[0]) if errors[0]: repo.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) + if firstbad[0]: + repo.ui.warn(_("(first damaged changeset appears to be %d)\n") + % firstbad[0]) return 1 diff --git a/tests/test-convert-cvs.out b/tests/test-convert-cvs.out --- a/tests/test-convert-cvs.out +++ b/tests/test-convert-cvs.out @@ -21,14 +21,10 @@ updating tags a c % commit new file revisions -Checking in a; src/a,v <-- a new revision: 1.2; previous revision: 1.1 -done -Checking in b/c; -src/b/c,v <-- c +src/b/c,v <-- b/c new revision: 1.2; previous revision: 1.1 -done % convert again destination src-hg is a Mercurial repository connecting to cvsrepo