On Sat, Dec 24, 2016 at 9:36 AM, Remi Chaintron <r...@fb.com> wrote:

> # 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'])
>

String literals in namedtuple declarations need u'' prefixes to prevent
Python 3 from barfing. This can likely be done as a follow-up, since Python
3 isn't officially supported.


> +# 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
>
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to