[PATCH 7 of 7] client: handle commit messages with \0 characters for all commands

Augie Fackler raf at durin42.com
Fri Mar 17 01:10:34 UTC 2023


Series LGTM, please feel encouraged to queue.

(I’m probably not a great reviewer for hglib at this point either, should we formally hand it over to someone else?)

> On Mar 14, 2023, at 04:26, Mathias De Mare <mathias.de_mare at nokia.com> wrote:
> 
> # HG changeset patch
> # User Mathias De Mare <mathias.de_mare at nokia.com>
> # Date 1678717940 -3600
> #      Mon Mar 13 15:32:20 2023 +0100
> # Node ID c2482b94ad1f644612d7e063e84d6f56b0d3b773
> # Parent  c1d60b0bf6f30b40fac5084132f0c0d266dfae82
> client: handle commit messages with \0 characters for all commands
> 
> Each of the impacted commands will now use the 'json' template,
> which they all support as of Mercurial 3.7.3 (the first version
> tested in the regression tests).
> 
> Note: I tried to add a test with null bytes,
> but both hglib and using hg directly through subprocess
> rejected adding a commit message with a null byte.
> 
> diff --git a/hglib/client.py b/hglib/client.py
> --- a/hglib/client.py
> +++ b/hglib/client.py
> @@ -159,20 +159,6 @@ class hgclient(object):
>             return channel, self.server.stdout.read(length)
> 
>     @staticmethod
> -    def _parserevs(splitted):
> -        '''splitted is a list of fields according to our rev.style, where
> -        each 6 fields compose one revision.
> -        '''
> -        revs = []
> -        for rev in util.grouper(7, splitted):
> -            # truncate the timezone and convert to a local datetime
> -            posixtime = float(rev[6].split(b('.'), 1)[0])
> -            dt = datetime.datetime.fromtimestamp(posixtime)
> -            revs.append(revision(rev[0], rev[1], rev[2], rev[3],
> -                                 rev[4], rev[5], dt))
> -        return revs
> -
> -    @staticmethod
>     def _parsejsonrevs(jsonrevs):
>         revs = []
>         for rev in jsonrevs:
> @@ -929,7 +915,7 @@ class hgclient(object):
>             rev = [rev]
> 
>         args = cmdbuilder(b('heads'), r=startrev, t=topological, c=closed,
> -                          template=templates.changeset, hidden=self.hidden,
> +                          template="json", hidden=self.hidden,
>                           *rev)
> 
>         def eh(ret, out, err):
> @@ -937,8 +923,12 @@ class hgclient(object):
>                 raise error.CommandError(args, ret, out, err)
>             return b('')
> 
> -        out = self.rawcommand(args, eh=eh).split(b('\0'))[:-1]
> -        return self._parserevs(out)
> +        out = self.rawcommand(args, eh=eh)
> +        if not out:
> +            return []
> +        json_out = json.loads(out)
> +
> +        return self._parsejsonrevs(json_out)
> 
>     def identify(self, rev=None, source=None, num=False, id=False, branch=False,
>                  tags=False, bookmarks=False):
> @@ -1036,7 +1026,7 @@ class hgclient(object):
> 
>         """
>         args = cmdbuilder(b('incoming'), path,
> -                          template=templates.changeset, r=revrange,
> +                          template="json", r=revrange,
>                           f=force, n=newest, bundle=bundle,
>                           B=bookmarks, b=branch, l=limit, M=nomerges,
>                           S=subrepos)
> @@ -1050,14 +1040,15 @@ class hgclient(object):
>             return []
> 
>         out = util.eatlines(out, 2)
> +
>         if bookmarks:
>             bms = []
>             for line in out.splitlines():
>                 bms.append(tuple(line.split()))
>             return bms
>         else:
> -            out = out.split(b('\0'))[:-1]
> -            return self._parserevs(out)
> +            json_out = json.loads(out)
> +            return self._parsejsonrevs(json_out)
> 
>     def log(self, revrange=None, files=[], follow=False,
>             followfirst=False, date=None, copies=False, keyword=None,
> @@ -1235,7 +1226,7 @@ class hgclient(object):
>         """
>         args = cmdbuilder(b('outgoing'),
>                           path,
> -                          template=templates.changeset, r=revrange,
> +                          template="json", r=revrange,
>                           f=force, n=newest, B=bookmarks,
>                           b=branch, S=subrepos)
> 
> @@ -1254,8 +1245,8 @@ class hgclient(object):
>                 bms.append(tuple(line.split()))
>             return bms
>         else:
> -            out = out.split(b('\0'))[:-1]
> -            return self._parserevs(out)
> +            json_out = json.loads(out)
> +            return self._parsejsonrevs(json_out)
> 
>     def parents(self, rev=None, file=None):
>         """Return the working directory's parent revisions. If rev is given,
> @@ -1265,16 +1256,19 @@ class hgclient(object):
>         is returned.
> 
>         """
> -        args = cmdbuilder(b('parents'), file, template=templates.changeset,
> +        args = cmdbuilder(b('parents'), file, template="json",
>                           r=rev, hidden=self.hidden)
> 
>         out = self.rawcommand(args)
>         if not out:
>             return
> 
> -        out = out.split(b('\0'))[:-1]
> +        json_out = json.loads(out)
> 
> -        return self._parserevs(out)
> +        if not json_out:
> +            return
> +
> +        return self._parsejsonrevs(json_out)
> 
>     def paths(self, name=None):
>         """
> @@ -1682,12 +1676,12 @@ class hgclient(object):
>         changeset most recently added to the repository (and therefore the most
>         recently changed head).
>         """
> -        args = cmdbuilder(b('tip'), template=templates.changeset,
> +        args = cmdbuilder(b('tip'), template="json",
>                           hidden=self.hidden)
>         out = self.rawcommand(args)
> -        out = out.split(b('\0'))
> +        json_out = json.loads(out)
> 
> -        return self._parserevs(out)[0]
> +        return self._parsejsonrevs(json_out)[0]
> 
>     def update(self, rev=None, clean=False, check=False, date=None):
>         """
> 
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at lists.mercurial-scm.org
> https://lists.mercurial-scm.org/mailman/listinfo/mercurial-devel



More information about the Mercurial-devel mailing list