From fba7e097edc11556b114ea3ed85fd8045fa30e0b Mon Sep 17 00:00:00 2001 From: Ivan Shcheklein Date: Tue, 25 Nov 2025 20:06:58 -0800 Subject: [PATCH 1/2] fix(pygit2) migrate ls_remotes to list_heads --- pyproject.toml | 3 ++- src/scmrepo/git/backend/pygit2/__init__.py | 31 ++++++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3334c0f..57e63b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,8 @@ dynamic = ["version"] dependencies = [ "gitpython>3", "dulwich>=0.24.0", - "pygit2>=1.14.0", + "pygit2>=1.14.0,<1.19.0; python_version < '3.11'", + "pygit2>=1.19.0; python_version >= '3.11'", "pygtrie>=2.3.2", "fsspec[tqdm]>=2024.2.0", "pathspec>=0.9.0", diff --git a/src/scmrepo/git/backend/pygit2/__init__.py b/src/scmrepo/git/backend/pygit2/__init__.py index fa40032..43f90ae 100644 --- a/src/scmrepo/git/backend/pygit2/__init__.py +++ b/src/scmrepo/git/backend/pygit2/__init__.py @@ -693,6 +693,26 @@ def _get_remote(self, url: str) -> Iterator["Remote"]: raise NotImplementedError yield remote + @staticmethod + def _get_remote_refs(remote: "Remote", callbacks) -> dict[str, "Oid"]: + """Get remote refs using the appropriate pygit2 API. + + pygit2 1.19.0 deprecated ls_remotes() in favor of list_heads(), + but 1.19.0+ requires Python 3.11+. + """ + if hasattr(remote, "list_heads"): + result: dict[str, Oid] = {} + for head in remote.list_heads(callbacks=callbacks, proxy=True): + assert head.name is not None + result[head.name] = head.oid + return result + return { + head["name"]: head["oid"] + for head in remote.ls_remotes( # type: ignore[attr-defined] + callbacks=callbacks, proxy=True + ) + } + def fetch_refspecs( self, url: str, @@ -731,14 +751,9 @@ def _default_status( SCMError(f"Git failed to fetch ref from '{url}'"), ): with RemoteCallbacks(progress=progress) as cb: - remote_refs: dict[str, Oid] = ( - { - head["name"]: head["oid"] - for head in remote.ls_remotes(callbacks=cb, proxy=True) - } - if not force - else {} - ) + remote_refs: dict[str, Oid] = {} + if not force: + remote_refs = self._get_remote_refs(remote, cb) remote.fetch( refspecs=refspecs, callbacks=cb, message="fetch", proxy=True ) From 3dd271b413a1b37df93e001faa0e380ffe16ee2c Mon Sep 17 00:00:00 2001 From: Ivan Shcheklein Date: Wed, 26 Nov 2025 21:40:19 -0800 Subject: [PATCH 2/2] drop redunant pygit2 safeguard --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 57e63b7..3334c0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,8 +26,7 @@ dynamic = ["version"] dependencies = [ "gitpython>3", "dulwich>=0.24.0", - "pygit2>=1.14.0,<1.19.0; python_version < '3.11'", - "pygit2>=1.19.0; python_version >= '3.11'", + "pygit2>=1.14.0", "pygtrie>=2.3.2", "fsspec[tqdm]>=2024.2.0", "pathspec>=0.9.0",