# HG changeset patch # User Remi Chaintron <r...@fb.com> # Date 1482596881 18000 # Sat Dec 24 11:28:01 2016 -0500 # Node ID c94d2907a470ca03b4a4a8da514b66d2f8952bce # Parent b1d220e584e6fc861a40a5aeefa0c3b19ae09126 revlog: processflags()
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -148,7 +148,9 @@ delta = self._chunk(chain.pop()) text = mdiff.patches(text, [delta]) - self.checkhash(text, node, rev=rev) + text, validatehash = self.processflags(text, self.flags(rev), raw=raw) + if validatehash is True: + self.checkhash(text, node, rev=rev) self._cache = (node, rev, text) return text diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -56,6 +56,10 @@ REVIDX_ISCENSORED = (1 << 15) # revision has censor metadata, must be verified REVIDX_DEFAULT_FLAGS = 0 REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED +# stable order in which flags need to be processed and their transforms applied +REVIDX_FLAGS_ORDER = [ + REVIDX_ISCENSORED, +] # max size of revlog with inline data _maxinline = 131072 @@ -65,6 +69,33 @@ LookupError = error.LookupError CensoredNodeError = error.CensoredNodeError +# 'flagtransform' namedtuple type for extensions to use to register transforms +# on revlog flags. +# - The apply transform will be used as a default behavior. +# - The applyraw transform will be used for changegroup generation and debug +# methods. +flagtransform = collections.namedtuple('flagtransform', ['apply', 'applyraw']) +# Store flag transforms (cf. 'addflagtransform()' to register) +_flagtransforms = { } + +def addflagtransform(flag, transform): + """Register transforms on revision data flags. + + Invariant: + - Flags need to be defined in REVIDX_KNOWN_FLAGS and REVIDX_FLAGS_ORDER. + - Only one transform can be registered on a specific flag. + - the transform must be of type 'flagtransform' + """ + if not flag & REVIDX_KNOWN_FLAGS: + raise error.Abort(_("cannot register transform on unknown flag.")) + if not flag in REVIDX_FLAGS_ORDER: + raise error.Abort(_("flag need to be defined in REVIDX_FLAGS_ORDER.")) + if _flagtransforms.get(flag, None) is not None: + raise error.Abort(_("cannot register multiple transforms on flag.")) + if not isinstance(transform, flagtransform): + raise error.Abort(_("invalid transform type.")) + _flagtransforms[flag] = transform + def getoffset(q): return int(q >> 16) @@ -1248,7 +1279,11 @@ bins = bins[1:] text = mdiff.patches(text, bins) - self.checkhash(text, node, rev=rev) + + text, validatehash = self.processflags(text, self.flags(rev), raw=raw) + if validatehash: + self.checkhash(text, node, rev=rev) + self._cache = (node, rev, text) return text @@ -1260,6 +1295,56 @@ """ return hash(text, p1, p2) + def processflags(self, text, flags, raw=False, reverse=False): + """Process revision flags and apply registered transforms. + + ``text`` - the revision data to process + ``flags`` - the revision flags + ``raw`` - an optional argument describing if the raw transform should be + applied. + ``reverse`` - an optional argument describing whether the flags should + be processed in order or reverse order. + + This method processes the flags in the order (or reverse order if + ``reverse`` is False) defined by REVIDX_FLAGS_ORDER, applying the + transforms registered for present flags. The order of flags defined in + REVIDX_FLAGS_ORDER needs to be stable for non-commutative + operations. + + If a ``flagtransform`` namedtuple has been registered on a flag, the + ``raw`` argument is used to determine which transform apply. If ``raw`` + is True, the ``applyraw`` field is used, ``apply`` if not (default). + If the ``raw`` argument is set, it indicates we are currently processing + flags in the context of changegroup generation or debug commands. + + Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the + processed text and ``validatehash`` is a bool indicating whether the + returned text should be checked for hash integrity. + """ + # Check all flags are known. + if flags & ~REVIDX_KNOWN_FLAGS: + raise RevlogError(_('incompatible revision flag %x') % + (flags & ~REVIDX_KNOWN_FLAGS)) + validatehash = True + # Depending on the operation (read or write), the order might be + # reversed due to non-commutative transforms. + orderedflags = REVIDX_FLAGS_ORDER + if reverse: + orderedflags = reversed(orderedflags) + + for flag in orderedflags: + # If a transform has been registered for a known flag, apply and + # update result tuple. + if flag & flags: + transform = _flagtransforms.get(flag, None) + if transform is not None: + apply, applyraw = transform + f = apply + if raw: + f = applyraw + text, validatehash = f(self, text) + return text, validatehash + def checkhash(self, text, node, p1=None, p2=None, rev=None): """Check node hash integrity. @@ -1447,7 +1532,11 @@ btext[0] = mdiff.patch(basetext, delta) try: - self.checkhash(btext[0], node, p1=p1, p2=p2) + btext[0], validatehash = self.processflags(btext[0], flags, + raw=raw, + reverse=True) + if validatehash is True: + self.checkhash(btext[0], node, p1=p1, p2=p2) if flags & REVIDX_ISCENSORED: raise RevlogError(_('node %s is not censored') % node) except CensoredNodeError: _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel