diff --git a/comfyui_manager/common/git_compat.py b/comfyui_manager/common/git_compat.py index 4367af57..747a5d98 100644 --- a/comfyui_manager/common/git_compat.py +++ b/comfyui_manager/common/git_compat.py @@ -42,6 +42,12 @@ if USE_PYGIT2: USE_PYGIT2 = False _PYGIT2_REQUESTED = False import git as _git + else: + # Disable owner validation once at import time. + # Required for Desktop 2.0 standalone installs where repo directories + # may be owned by a different user (e.g., system-installed paths). + # See CVE-2022-24765 for context on this validation. + _pygit2.option(_pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0) if not USE_PYGIT2: import git as _git @@ -372,7 +378,6 @@ class _GitPythonRepo(GitRepo): class _Pygit2Repo(GitRepo): def __init__(self, path): - _pygit2.option(_pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0) repo_path = os.path.abspath(path) git_dir = os.path.join(repo_path, '.git') for sub in ['refs/heads', 'refs/tags', 'refs/remotes']: @@ -750,18 +755,24 @@ class _Pygit2Repo(GitRepo): try: self._repo.submodules.init() self._repo.submodules.update() - except (AttributeError, Exception) as e: + except Exception as e: import subprocess try: - subprocess.run( + result = subprocess.run( ['git', 'submodule', 'update', '--init', '--recursive'], cwd=self._working_dir, capture_output=True, timeout=120, ) + if result.returncode != 0: + raise GitCommandError( + f"submodule update failed (exit {result.returncode}): " + f"{result.stderr.decode(errors='replace')}") except FileNotFoundError: - print(f"[ComfyUI-Manager] pygit2: submodule update requires system git (not installed): {e}", file=sys.stderr) - except Exception: - print(f"[ComfyUI-Manager] pygit2: submodule update failed: {e}", file=sys.stderr) + print(f"[ComfyUI-Manager] pygit2: submodule update requires system git (not installed)", file=sys.stderr) + except GitCommandError: + raise + except Exception as sub_e: + print(f"[ComfyUI-Manager] pygit2: submodule update failed: {sub_e}", file=sys.stderr) def clear_cache(self): pass @@ -813,9 +824,10 @@ def clone_repo(url, dest, progress=None): (checkout, clear_cache, close, etc.). """ if USE_PYGIT2: - _pygit2.option(_pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0) _pygit2.clone_repository(url, dest) - return _Pygit2Repo(dest) + repo = _Pygit2Repo(dest) + repo.submodule_update() + return repo else: if progress is None: r = _git.Repo.clone_from(url, dest, recursive=True) diff --git a/comfyui_manager/glob/manager_core.py b/comfyui_manager/glob/manager_core.py index a61f9a17..187e91e0 100644 --- a/comfyui_manager/glob/manager_core.py +++ b/comfyui_manager/glob/manager_core.py @@ -44,7 +44,7 @@ from ..common.enums import NetworkMode, SecurityLevel, DBMode from ..common import context -version_code = [4, 1] +version_code = [4, 2] version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') @@ -2282,31 +2282,28 @@ def git_pull(path): if platform.system() == "Windows": return __win_check_git_pull(path) else: - repo = open_repo(path) + with open_repo(path) as repo: + if repo.is_dirty(): + print(f"STASH: '{path}' is dirty.") + repo.stash() - if repo.is_dirty(): - print(f"STASH: '{path}' is dirty.") - repo.stash() + if repo.head_is_detached: + if not switch_to_default_branch(repo): + raise ValueError(f"Failed to switch to default branch while pulling: {path}") - if repo.head_is_detached: - if not switch_to_default_branch(repo): - raise ValueError(f"Failed to switch to default branch while pulling: {path}") + branch_name = repo.active_branch_name + remote_name = repo.get_tracking_remote_name() - branch_name = repo.active_branch_name - remote_name = repo.get_tracking_remote_name() + try: + repo.pull_ff_only() + except GitCommandError: + backup_name = get_backup_branch_name(repo) + repo.create_backup_branch(backup_name) + logging.info(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}") + repo.reset_hard(f'{remote_name}/{branch_name}') + logging.info(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}") - try: - repo.pull_ff_only() - except GitCommandError: - backup_name = get_backup_branch_name(repo) - repo.create_backup_branch(backup_name) - logging.info(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}") - repo.reset_hard(f'{remote_name}/{branch_name}') - logging.info(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}") - - repo.submodule_update() - - repo.close() + repo.submodule_update() return True diff --git a/comfyui_manager/legacy/manager_core.py b/comfyui_manager/legacy/manager_core.py index 5d522149..56e01f3f 100644 --- a/comfyui_manager/legacy/manager_core.py +++ b/comfyui_manager/legacy/manager_core.py @@ -42,7 +42,7 @@ from ..common.enums import NetworkMode, SecurityLevel, DBMode from ..common import context -version_code = [4, 1] +version_code = [4, 2] version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') diff --git a/pyproject.toml b/pyproject.toml index 271ed03f..cb5a4132 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "comfyui-manager" license = { text = "GPL-3.0-only" } -version = "4.1" +version = "4.2b1" requires-python = ">= 3.9" description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI." readme = "README.md" @@ -39,7 +39,7 @@ dependencies = [ ] [project.optional-dependencies] -dev = ["pre-commit", "pytest", "ruff", "pytest-cov"] +dev = ["pre-commit", "pytest", "ruff", "pytest-cov", "pygit2"] [project.urls] Repository = "https://github.com/ltdrdata/ComfyUI-Manager" diff --git a/requirements.txt b/requirements.txt index d225a63c..22be6974 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ GitPython +pygit2 PyGithub # matrix-nio transformers