[PATCH] convert: use pygit2 if available, to improve performance

Patrick Mézard patrick at mezard.eu
Fri Apr 6 07:51:16 CDT 2012


Le 05/04/12 23:53, Bryan O'Sullivan a écrit :
> # HG changeset patch
> # User Bryan O'Sullivan <bryano at fb.com>
> # Date 1333662769 25200
> # Branch stable
> # Node ID d6a14f098965261ca2e1722d711bf9f7789ae3c2
> # Parent  4d875bb546dc03db33630f5388d7e04939c386a0
> convert: use pygit2 if available, to improve performance
> 
> When converting a git repository, the main bottleneck is shelling out to
> git to retrieve data.  This patch uses the pygit2 bindings to libgit2,
> if available, to avoid most callouts to git.  Since the pygit2 bindings
> are currently incomplete, we still need to use git for some tasks.
> 
> This patch requires version 0.16.1 or newer of pygit2.  If pygit2
> is not available or too old, we transparently fall back to invoking
> git directly.
> 
> diff -r 4d875bb546dc -r d6a14f098965 hgext/convert/git.py
> --- a/hgext/convert/git.py	Tue Apr 03 22:01:28 2012 +0200
> +++ b/hgext/convert/git.py	Thu Apr 05 14:52:49 2012 -0700
> @@ -12,7 +12,22 @@
>  
>  from common import NoRepo, commit, converter_source, checktool
>  
> -class convert_git(converter_source):
> +class convert_git_base(converter_source):

FWIW, we are trying to move away from names with underscores.

[...]

> +
> +def hexoid(obj):
> +    # pygit2's "hex" property is unicode, but "oid" is str
> +    return obj.oid.encode('hex')
> +
> +class nopygit2(Exception):
> +    pass

Maybe s/nopygit2/NoPyGit2/

> +class convert_git_pygit2(convert_git_base):
> +    def __init__(self, ui, path, rev):
> +        super(convert_git_pygit2, self).__init__(ui, path, rev=rev)
> +        try:
> +            # check for pygit2 0.16.1 or newer
> +            import pygit2
> +            pygit2.Commit._message
> +        except (AttributeError, ImportError):
> +            raise nopygit2
> +        self.repo = pygit2.init_repository(path, True)
> +
> +    def getheads(self):
> +        if not self.rev:
> +            return [hexoid(self.repo.lookup_reference(r).resolve())
> +                    for r in self.repo.listall_references()
> +                    if (r.startswith('refs/heads/') or
> +                        r.startswith('refs/remotes/'))]
> +        else:
> +            try:
> +                return [hexoid(repo.lookup_reference(self.rev).resolve())]
> +            except KeyError:
> +                return [hexoid(repo[self.rev])]
> +
> +    def getcommit(self, rev):
> +        def prettyname(sig):
> +            if sig._name:
> +                return '%s <%s>' % (sig._name, sig._email)
> +            return sig._email
> +
> +        c = self.repo[rev.decode('hex')]
> +        message = c._message
> +        author = prettyname(c.author)
> +        committer = prettyname(c.committer)
> +        if author != committer:
> +            message += '\ncommitter: %s\n' % committer
> +        return commit(parents=[hexoid(p) for p in c.parents],
> +                      date='%s %s' % (c.commit_time, c.commit_time_offset),

Looks like c.commit_time_offset is in minutes and we want it backward:

                         date='%s %s' % (c.commit_time, -c.commit_time_offset*60),

> +                      author=author, desc=self.recode(message), rev=rev)
> +

[...]

> -
>      def getbookmarks(self):
>          bookmarks = {}
>  
> @@ -205,3 +268,9 @@
>                  pass
>  
>          return bookmarks

The bookmarks stuff was not implemented in convert_git_pygit2, should it be left in convert_git_base?

> +
> +def convert_git(ui, path, rev=None):
> +    try:
> +        return convert_git_pygit2(ui, path, rev)
> +    except nopygit2:
> +        return convert_git_plain(ui, path, rev)

--
Patrick Mézard


More information about the Mercurial-devel mailing list