From 498e896472b030525d8d761824ab5a23bef50828 Mon Sep 17 00:00:00 2001 From: Jedrzej Kosinski Date: Tue, 9 Jun 2026 20:59:45 -0700 Subject: [PATCH] fix(git_compat): ignore global git config in pygit2 backend Under Desktop 2.0 the launcher sets CM_USE_PYGIT2=1, so the pygit2 backend ran clone_repository/remote.fetch with no credentials callback and honored the user's global git config. An insteadOf rewrite (https->ssh) or credential helper then forced authentication, failing with 'authentication required but no callback set'. Blank the system/global/XDG config search path at import time so libgit2 operations are hermetic, and normalize SSH-form GitHub URLs to anonymous HTTPS on clone and when opening a repo. Amp-Thread-ID: https://ampcode.com/threads/T-019eafa0-16a1-726e-91a4-dac1a40d4481 Co-authored-by: Amp --- comfyui_manager/common/git_compat.py | 52 +++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/comfyui_manager/common/git_compat.py b/comfyui_manager/common/git_compat.py index 5fa0501d..63fe3dad 100644 --- a/comfyui_manager/common/git_compat.py +++ b/comfyui_manager/common/git_compat.py @@ -14,11 +14,28 @@ Exports: """ import os +import re import sys from abc import ABC, abstractmethod from collections import deque from datetime import datetime, timezone, timedelta + +def _to_https_url(url): + """Rewrite an SSH-form git URL to its anonymous HTTPS equivalent. + + Handles `git@host:owner/repo(.git)` and `ssh://git@host/owner/repo(.git)`. + Returns the URL unchanged if it is not SSH-form, so pygit2 clone/fetch + of public repos never requires SSH credentials even when a repo's own + config stores an SSH origin. + """ + if not url: + return url + m = re.match(r"^(?:ssh://)?git@([^:/]+)[:/](.+)$", url) + if m: + return "https://%s/%s" % (m.group(1), m.group(2)) + return url + # --------------------------------------------------------------------------- # Backend selection # --------------------------------------------------------------------------- @@ -49,6 +66,27 @@ if USE_PYGIT2: # See CVE-2022-24765 for context on this validation. _pygit2.option(_pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0) + # Ignore system/global/XDG git config for libgit2 operations. A + # user's global config can carry `insteadOf` rewrites (e.g. + # https->ssh) or credential helpers that force authentication, + # which libgit2 cannot satisfy without a credentials callback + # ("authentication required but no callback set"). Blanking the + # config search path keeps clone/fetch over anonymous HTTPS. + try: + from pygit2.enums import ConfigLevel as _ConfigLevel + _cfg_levels = [_ConfigLevel.SYSTEM, _ConfigLevel.XDG, _ConfigLevel.GLOBAL] + except (ImportError, AttributeError): + _cfg_levels = [ + _pygit2.GIT_CONFIG_LEVEL_SYSTEM, + _pygit2.GIT_CONFIG_LEVEL_XDG, + _pygit2.GIT_CONFIG_LEVEL_GLOBAL, + ] + for _lvl in _cfg_levels: + try: + _pygit2.settings.search_path[_lvl] = "" + except Exception: + pass + if not USE_PYGIT2: import git as _git @@ -387,6 +425,18 @@ class _Pygit2Repo(GitRepo): pass self._repo = _pygit2.Repository(git_dir) self._working_dir = repo_path + self._normalize_remote_urls() + + def _normalize_remote_urls(self): + """Rewrite any SSH-form remote URLs to anonymous HTTPS so fetch/pull + never require SSH credentials under the pygit2 backend.""" + for remote in self._repo.remotes: + https_url = _to_https_url(remote.url) + if https_url != remote.url: + try: + self._repo.remotes.set_url(remote.name, https_url) + except Exception: + pass @property def working_dir(self): @@ -824,7 +874,7 @@ def clone_repo(url, dest, progress=None): (checkout, clear_cache, close, etc.). """ if USE_PYGIT2: - _pygit2.clone_repository(url, dest) + _pygit2.clone_repository(_to_https_url(url), dest) repo = _Pygit2Repo(dest) repo.submodule_update() return repo