diff --git a/hgext/git/__init__.py b/hgext/git/__init__.py --- a/hgext/git/__init__.py +++ b/hgext/git/__init__.py @@ -8,8 +8,6 @@ import os -import pygit2 - from mercurial.i18n import _ from mercurial import ( @@ -29,7 +27,6 @@ index, ) - # TODO: extract an interface for this in core class gitstore(object): # store.basicstore): def __init__(self, path, vfstype): @@ -39,7 +36,7 @@ # above lines should go away in favor of: # super(gitstore, self).__init__(path, vfstype) - self.git = pygit2.Repository( + self.git = gitutil.get_pygit2().Repository( os.path.normpath(os.path.join(path, b'..', b'.git')) ) self._progress_factory = lambda *args, **kwargs: None @@ -89,6 +86,16 @@ def _makestore(orig, requirements, storebasepath, vfstype): + # Check for presence of pygit2 only here. The assumption is that we'll + # run this code iff we'll later need pygit2. + if gitutil.get_pygit2() is None: + raise error.Abort( + _( + b'the git extension requires the Python ' + b'pygit2 library to be installed' + ) + ) + if os.path.exists( os.path.join(storebasepath, b'this-is-git') ) and os.path.exists(os.path.join(storebasepath, b'..', b'.git')): @@ -156,7 +163,7 @@ if k in self: return self[k] return default - except pygit2.InvalidSpecError: + except gitutil.get_pygit2().InvalidSpecError: return default @property diff --git a/hgext/git/dirstate.py b/hgext/git/dirstate.py --- a/hgext/git/dirstate.py +++ b/hgext/git/dirstate.py @@ -4,8 +4,6 @@ import errno import os -import pygit2 - from mercurial import ( error, extensions, @@ -22,6 +20,8 @@ from . import gitutil +pygit2 = gitutil.get_pygit2() + def readpatternfile(orig, filepath, warn, sourceinfo=False): if not (b'info/exclude' in filepath or filepath.endswith(b'.gitignore')): @@ -46,23 +46,25 @@ extensions.wrapfunction(matchmod, b'readpatternfile', readpatternfile) -_STATUS_MAP = { - pygit2.GIT_STATUS_CONFLICTED: b'm', - pygit2.GIT_STATUS_CURRENT: b'n', - pygit2.GIT_STATUS_IGNORED: b'?', - pygit2.GIT_STATUS_INDEX_DELETED: b'r', - pygit2.GIT_STATUS_INDEX_MODIFIED: b'n', - pygit2.GIT_STATUS_INDEX_NEW: b'a', - pygit2.GIT_STATUS_INDEX_RENAMED: b'a', - pygit2.GIT_STATUS_INDEX_TYPECHANGE: b'n', - pygit2.GIT_STATUS_WT_DELETED: b'r', - pygit2.GIT_STATUS_WT_MODIFIED: b'n', - pygit2.GIT_STATUS_WT_NEW: b'?', - pygit2.GIT_STATUS_WT_RENAMED: b'a', - pygit2.GIT_STATUS_WT_TYPECHANGE: b'n', - pygit2.GIT_STATUS_WT_UNREADABLE: b'?', - pygit2.GIT_STATUS_INDEX_MODIFIED | pygit2.GIT_STATUS_WT_MODIFIED: 'm', -} +_STATUS_MAP = {} +if pygit2: + _STATUS_MAP = { + pygit2.GIT_STATUS_CONFLICTED: b'm', + pygit2.GIT_STATUS_CURRENT: b'n', + pygit2.GIT_STATUS_IGNORED: b'?', + pygit2.GIT_STATUS_INDEX_DELETED: b'r', + pygit2.GIT_STATUS_INDEX_MODIFIED: b'n', + pygit2.GIT_STATUS_INDEX_NEW: b'a', + pygit2.GIT_STATUS_INDEX_RENAMED: b'a', + pygit2.GIT_STATUS_INDEX_TYPECHANGE: b'n', + pygit2.GIT_STATUS_WT_DELETED: b'r', + pygit2.GIT_STATUS_WT_MODIFIED: b'n', + pygit2.GIT_STATUS_WT_NEW: b'?', + pygit2.GIT_STATUS_WT_RENAMED: b'a', + pygit2.GIT_STATUS_WT_TYPECHANGE: b'n', + pygit2.GIT_STATUS_WT_UNREADABLE: b'?', + pygit2.GIT_STATUS_INDEX_MODIFIED | pygit2.GIT_STATUS_WT_MODIFIED: 'm', + } @interfaceutil.implementer(intdirstate.idirstate) diff --git a/hgext/git/gitlog.py b/hgext/git/gitlog.py --- a/hgext/git/gitlog.py +++ b/hgext/git/gitlog.py @@ -1,7 +1,5 @@ from __future__ import absolute_import -import pygit2 - from mercurial.i18n import _ from mercurial import ( @@ -25,6 +23,8 @@ manifest as gitmanifest, ) +pygit2 = gitutil.get_pygit2() + class baselog(object): # revlog.revlog): """Common implementations between changelog and manifestlog.""" diff --git a/hgext/git/gitutil.py b/hgext/git/gitutil.py --- a/hgext/git/gitutil.py +++ b/hgext/git/gitutil.py @@ -5,6 +5,20 @@ from mercurial import pycompat +pygit2_module = None + + +def get_pygit2(): + global pygit2_module + if pygit2_module is None: + try: + import pygit2 as pygit2_module + + pygit2_module.InvalidSpecError + except (ImportError, AttributeError): + pass + return pygit2_module + def togitnode(n): """Wrapper to convert a Mercurial binary node to a unicode hexlified node. diff --git a/hgext/git/index.py b/hgext/git/index.py --- a/hgext/git/index.py +++ b/hgext/git/index.py @@ -4,8 +4,6 @@ import os import sqlite3 -import pygit2 - from mercurial.i18n import _ from mercurial import ( @@ -18,6 +16,8 @@ from . import gitutil +pygit2 = gitutil.get_pygit2() + _CURRENT_SCHEMA_VERSION = 1 _SCHEMA = ( """ @@ -101,9 +101,13 @@ return db -_OUR_ORDER = ( - pygit2.GIT_SORT_TOPOLOGICAL | pygit2.GIT_SORT_TIME | pygit2.GIT_SORT_REVERSE -) +_OUR_ORDER = () +if pygit2: + _OUR_ORDER = ( + pygit2.GIT_SORT_TOPOLOGICAL + | pygit2.GIT_SORT_TIME + | pygit2.GIT_SORT_REVERSE + ) _DIFF_FLAGS = 1 << 21 # GIT_DIFF_FORCE_BINARY, which isn't exposed by pygit2 diff --git a/hgext/git/manifest.py b/hgext/git/manifest.py --- a/hgext/git/manifest.py +++ b/hgext/git/manifest.py @@ -1,7 +1,5 @@ from __future__ import absolute_import -import pygit2 - from mercurial import ( match as matchmod, pathutil, @@ -15,6 +13,9 @@ from . import gitutil +pygit2 = gitutil.get_pygit2() + + @interfaceutil.implementer(repository.imanifestdict) class gittreemanifest(object): """Expose git trees (and optionally a builder's overlay) as a manifestdict.