Patchwork D8268: git: don't fail import when pygit2 is not install

login
register
mail settings
Submitter phabricator
Date March 9, 2020, 10:58 p.m.
Message ID <9427b6d2f5b6b56af2bcad413181f7a7@localhost.localdomain>
Download mbox | patch
Permalink /patch/45647/
State Not Applicable
Headers show

Comments

phabricator - March 9, 2020, 10:58 p.m.
Closed by commit rHGec54b3d2af0b: git: don&#039;t fail import when pygit2 is not install (authored by martinvonz).
martinvonz marked an inline comment as done.
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8268?vs=20646&id=20649

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8268/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8268

AFFECTED FILES
  hgext/git/__init__.py
  hgext/git/dirstate.py
  hgext/git/gitlog.py
  hgext/git/gitutil.py
  hgext/git/index.py
  hgext/git/manifest.py

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mharbison72, mercurial-devel

Patch

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.
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/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/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/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/__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