Commit Graph

3 Commits

Author SHA1 Message Date
Dr.Lt.Data
8b98723b42
fix(git_compat): follow-ups for pygit2 fallback hardening (#2974)
Some checks failed
Python Linting / Run Ruff (push) Waiting to run
Publish to PyPI / build-and-publish (push) Has been cancelled
- Route list_remotes() fetch through _fetch_remote so the proxy and
  SSH-to-HTTPS rewrite apply to every fetch entry point, and provide
  pull on its proxies (parity with get_remote and the GitPython proxy)
  via a shared _pull_remote helper
- Rework _to_https_url: handle ssh://git@host:port/... URLs (drop the
  custom SSH port instead of mangling it into the path) and collapse
  leading slashes so git@host:/abs/path no longer yields a double-slash
  URL. Behavior narrowing: colon-less git@host/path (not a valid
  scp-form URL), ssh:// URLs with a port but no path, and IPv6 ssh://
  URLs are now returned unchanged instead of being wrongly converted
- clone_repo: omit the proxy= kwarg when no proxy is configured, so
  proxy-less installs keep working on pygit2 older than 1.18
- Simplify redundant except (KeyError, Exception) clause
- Require pygit2>=1.18 (clone_repository proxy= parameter)
- Add unit tests for _to_https_url (incl. negative cases pinning the
  narrowing) and a regression test that list_remotes proxies route
  fetch/pull through their own remote (late-binding guard)
2026-06-10 18:19:55 +09:00
Jedrzej Kosinski
622a7077a5
fix(git_compat): harden pygit2 fallback path; prefer system git when available (#2972)
Some checks are pending
Python Linting / Run Ruff (push) Waiting to run
* 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 <amp@ampcode.com>

* fix(git_compat): preserve corporate http.proxy in pygit2 backend

Snapshot http.proxy from the global git config before blanking the config search path, then pass it explicitly (proxy=) to clone_repository and every remote.fetch() in the pygit2 backend, so corporate-lockdown proxy setups keep working after the insteadOf/SSH hardening.

Amp-Thread-ID: https://ampcode.com/threads/T-019eafa0-16a1-726e-91a4-dac1a40d4481
Co-authored-by: Amp <amp@ampcode.com>

* fix(git_compat): stop rewriting repo remotes on disk under pygit2 backend

Removing _normalize_remote_urls(): persistently rewriting a repo's SSH origin
to HTTPS mutates on-disk repo state, which is risky if interrupted. The pygit2
backend already neutralizes auth-forcing global config (insteadOf, credential
helpers) by blanking libgit2's config search path, so anonymous HTTPS fetch
works without touching the stored remote.

Manager already prefers the GitPython/system-git backend when a system git is
present (which honors the user's full git config including insteadOf https->ssh
and proxies), and only uses the bundled pygit2 when system git is absent or
CM_USE_PYGIT2=1 is set.

Amp-Thread-ID: https://ampcode.com/threads/T-019eafa0-16a1-726e-91a4-dac1a40d4481
Co-authored-by: Amp <amp@ampcode.com>

* fix(git_compat): fetch SSH-origin repos via in-memory anonymous HTTPS

Consolidate the five pygit2 fetch sites into a single _fetch_remote helper.
When a repo's stored origin is SSH-form (git@host:owner/repo), the bundled
pygit2 (no SSH transport) would fail with an auth error; fetch through an
in-memory anonymous remote over HTTPS instead, leaving .git/config untouched.
Also closes a proxy hole where get_remote() exposed remote.fetch without the
preserved http.proxy.

Validated against both backends (pygit2 1.19.2 + GitPython): all 47
git_compat tests pass; verified create_anonymous fetch updates
refs/remotes/origin/* without persisting any remote or rewriting origin.

Amp-Thread-ID: https://ampcode.com/threads/T-019eafa0-16a1-726e-91a4-dac1a40d4481
Co-authored-by: Amp <amp@ampcode.com>

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-06-10 16:33:18 +09:00
Jedrzej Kosinski
49e205acd4
feat: add pygit2 compatibility wrapper for standalone Desktop 2.0 installs (#2719)
Some checks failed
Publish to PyPI / build-and-publish (push) Has been cancelled
Python Linting / Run Ruff (push) Has been cancelled
* feat: add pygit2 compatibility wrapper for standalone Desktop 2.0 installs

Add git_compat.py abstraction layer that wraps both GitPython and pygit2
behind a unified GitRepo interface. When CM_USE_PYGIT2=1 is set (by the
Desktop 2.0 Launcher for standalone installs), or when system git is not
available, the pygit2 backend is used automatically.

Key changes:
- New comfyui_manager/common/git_compat.py with abstract GitRepo base class,
  _GitPythonRepo (1:1 pass-throughs) and _Pygit2Repo implementations
- All 6 non-legacy files updated to use the wrapper:
  - comfyui_manager/glob/manager_core.py (14 git.Repo usages)
  - comfyui_manager/common/git_helper.py (7 git.Repo usages)
  - comfyui_manager/common/context.py (1 usage)
  - comfyui_manager/glob/utils/environment_utils.py (2 usages)
  - cm_cli/__main__.py (1 usage)
  - comfyui_manager/common/timestamp_utils.py (repo.heads usage)
- get_script_env() propagates CM_USE_PYGIT2 to subprocesses
- git_helper.py uses sys.path.insert to find git_compat as standalone script
- All repo handles wrapped in context managers to prevent resource leaks
- get_head_by_name returns _HeadProxy for interface consistency
- Submodule fallback logs clear message when system git is absent
- 47 tests comparing both backends via subprocess isolation

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019d0ec5-cb9f-74df-a1a2-0c8154a330b3

* fix(pygit2): address review findings + bump version to 4.2b1

- C1: add submodule_update() after pygit2 clone for recursive parity
- C2: check subprocess returncode in submodule_update fallback
- C3: move GIT_OPT_SET_OWNER_VALIDATION to module-level (once at import)
- H1: use context manager in git_pull() to prevent resource leaks
- Bump version to 4.2b1, version_code to [4, 2]
- Add pygit2 to dev dependencies and requirements.txt

* style: fix ruff F841 unused variable and F541 unnecessary f-string

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Dr.Lt.Data <dr.lt.data@gmail.com>
2026-03-27 08:42:26 +09:00