From 43092d422dbda0dc26913a6af292b2417169049f Mon Sep 17 00:00:00 2001 From: Peter Rowlands Date: Thu, 3 Nov 2022 14:37:42 +0900 Subject: [PATCH 1/2] dulwich: workaround for codespaces system config --- src/scmrepo/git/backend/dulwich/__init__.py | 30 ++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/scmrepo/git/backend/dulwich/__init__.py b/src/scmrepo/git/backend/dulwich/__init__.py index 2c0910ce..d36bda2a 100644 --- a/src/scmrepo/git/backend/dulwich/__init__.py +++ b/src/scmrepo/git/backend/dulwich/__init__.py @@ -291,12 +291,36 @@ def commit(self, msg: str, no_verify: bool = False): try: commit(self.root_dir, message=msg, no_verify=no_verify) except InvalidUserIdentity as exc: - raise SCMError( - "Git username and email must be configured" - ) from exc + identity = self._get_codespaces_identity() + if identity is not None: + commit( + self.root_dir, + message=msg, + no_verify=no_verify, + committer=identity, + author=identity, + ) + else: + raise SCMError( + "Git username and email must be configured" + ) from exc except TimezoneFormatError as exc: raise SCMError("Invalid Git timestamp") from exc + def _get_codespaces_identity(self) -> Optional[bytes]: + from dulwich.config import ConfigFile, StackedConfig + from dulwich.repo import get_user_identity + + if "CODESPACES" not in os.environ: + return None + try: + config = StackedConfig( + [ConfigFile.from_path("/usr/local/etc/gitconfig")] + ) + return get_user_identity(config) + except Exception: # pylint: disable=broad-except + return None + def checkout( self, branch: str, From 6434a0cf02568b51a9877909cf18cc9458b4c214 Mon Sep 17 00:00:00 2001 From: Peter Rowlands Date: Thu, 3 Nov 2022 14:37:57 +0900 Subject: [PATCH 2/2] pygit2: workaround for codespaces system config --- src/scmrepo/git/backend/pygit2.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/scmrepo/git/backend/pygit2.py b/src/scmrepo/git/backend/pygit2.py index c87acc09..1cef2c9c 100644 --- a/src/scmrepo/git/backend/pygit2.py +++ b/src/scmrepo/git/backend/pygit2.py @@ -15,7 +15,7 @@ Union, ) -from funcy import cached_property +from funcy import cached_property, first from scmrepo.exceptions import ( CloneError, @@ -32,6 +32,8 @@ if TYPE_CHECKING: + from pygit2 import Signature + from scmrepo.progress import GitProgressEvent @@ -123,14 +125,32 @@ def _resolve_refish(self, refish: str): return commit, ref @property - def default_signature(self): + def default_signature(self) -> "Signature": try: return self.repo.default_signature except KeyError as exc: + signature = self._get_codespaces_signature() + if signature is not None: + return signature raise SCMError( "Git username and email must be configured" ) from exc + def _get_codespaces_signature(self) -> Optional["Signature"]: + from pygit2 import Config, Signature + + if "CODESPACES" not in os.environ: + return None + try: + config = Config("/usr/local/etc/gitconfig") + name = first(config.get_multivar("user.name")) + email = first(config.get_multivar("user.email")) + if name and email: + return Signature(name, email) + except Exception: # pylint: disable=broad-except + pass + return None + @staticmethod def _get_checkout_strategy(strategy: Optional[int] = None): from pygit2 import (