comparison mercurial/localrepo.py @ 10418:5fc090ba08a6

localrepo: add optional validation (defaults to off) for incoming changes This verifies that all manifests are present for incoming changes, and all files for those manifests are also present. This is a simple first-pass, and could be better, but seems like a valuable thing to have, as I've seen pushes in the past that propagated revlog corruption.
author Augie Fackler <durin42@gmail.com>
date Thu, 11 Feb 2010 16:37:43 -0600
parents 2d30d66a89ad
children 1c50a954a524
comparison
equal deleted inserted replaced
10416:4cfd0d56be6d 10418:5fc090ba08a6
2003 # if the result of the merge of 1 and 2 is the same in 3 and 4, 2003 # if the result of the merge of 1 and 2 is the same in 3 and 4,
2004 # no new manifest will be created and the manifest group will 2004 # no new manifest will be created and the manifest group will
2005 # be empty during the pull 2005 # be empty during the pull
2006 self.manifest.addgroup(chunkiter, revmap, trp) 2006 self.manifest.addgroup(chunkiter, revmap, trp)
2007 2007
2008 needfiles = {}
2009 if self.ui.configbool('server', 'validate', default=False):
2010 # validate incoming csets have their manifests
2011 for cset in xrange(clstart, clend):
2012 mfest = self.changelog.read(self.changelog.node(cset))[0]
2013 mfest = self.manifest.readdelta(mfest)
2014 # store file nodes we must see
2015 for f, n in mfest.iteritems():
2016 needfiles.setdefault(f, set()).add(n)
2017
2008 # process the files 2018 # process the files
2009 self.ui.status(_("adding file changes\n")) 2019 self.ui.status(_("adding file changes\n"))
2010 while 1: 2020 while 1:
2011 f = changegroup.getchunk(source) 2021 f = changegroup.getchunk(source)
2012 if not f: 2022 if not f:
2017 chunkiter = changegroup.chunkiter(source) 2027 chunkiter = changegroup.chunkiter(source)
2018 if fl.addgroup(chunkiter, revmap, trp) is None: 2028 if fl.addgroup(chunkiter, revmap, trp) is None:
2019 raise util.Abort(_("received file revlog group is empty")) 2029 raise util.Abort(_("received file revlog group is empty"))
2020 revisions += len(fl) - o 2030 revisions += len(fl) - o
2021 files += 1 2031 files += 1
2032 if f in needfiles:
2033 needs = needfiles[f]
2034 for new in xrange(o, len(fl)):
2035 n = fl.node(new)
2036 if n in needs:
2037 needs.remove(n)
2038 if not needs:
2039 del needfiles[f]
2040
2041 for f, needs in needfiles.iteritems():
2042 fl = self.file(f)
2043 for n in needs:
2044 try:
2045 fl.rev(n)
2046 except error.LookupError:
2047 raise util.Abort(
2048 _('missing file data for %s:%s - run hg verify') %
2049 (f, hex(n)))
2022 2050
2023 newheads = len(cl.heads()) 2051 newheads = len(cl.heads())
2024 heads = "" 2052 heads = ""
2025 if oldheads and newheads != oldheads: 2053 if oldheads and newheads != oldheads:
2026 heads = _(" (%+d heads)") % (newheads - oldheads) 2054 heads = _(" (%+d heads)") % (newheads - oldheads)