From 41ab628f995f77439c293bab1a7c431cb901e206 Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Sat, 21 Mar 2026 21:03:34 +0900 Subject: [PATCH] =?UTF-8?q?fix(git=5Fhelper):=20Windows=20subprocess=20cra?= =?UTF-8?q?sh=20fix=20=E2=80=94=20reinstall=20URL=20handling=20+=20tqdm=20?= =?UTF-8?q?pipe=20deadlock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes for Windows E2E failures: 1. cm_cli reinstall_node(): resolve_node_spec() returns the full URL as node_name, but internal dicts are keyed by repo basename or cnr_id. Use get_cnr_by_repo() for CNR-aware lookup with correct is_unknown flag, falling back to basename for unknown nodes. 2. git_helper.py gitclone(): disable tqdm progress when stderr is piped (sys.stderr.isatty() gate). When a parent process captures stderr via PIPE, tqdm output fills the 4KB Windows pipe buffer, blocking GitPython's progress reader and causing git clone exit 128. --- cm_cli/__main__.py | 29 +++++++++++++++++++--------- comfyui_manager/common/git_helper.py | 6 +++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/cm_cli/__main__.py b/cm_cli/__main__.py index b302872c..554a7e03 100644 --- a/cm_cli/__main__.py +++ b/cm_cli/__main__.py @@ -238,18 +238,29 @@ def install_node(node_spec_str, is_all=False, cnt_msg='', **kwargs): def reinstall_node(node_spec_str, is_all=False, cnt_msg=''): - node_spec = unified_manager.resolve_node_spec(node_spec_str) + if core.is_valid_url(node_spec_str): + # URL-based: resolve_node_spec returns the full URL as node_name, + # but internal dicts are keyed by repo basename or cnr_id. + url = node_spec_str.rstrip('/') + cnr = unified_manager.get_cnr_by_repo(url) + if cnr: + node_id = cnr['id'] + unified_manager.unified_uninstall(node_id, False) + unified_manager.purge_node_state(node_id) + else: + repo_name = os.path.splitext(os.path.basename(url))[0] + unified_manager.unified_uninstall(repo_name, True) + unified_manager.purge_node_state(repo_name) - node_name, version_spec, _ = node_spec + install_node(node_spec_str, is_all=is_all, cnt_msg=cnt_msg, raise_on_fail=True) + else: + node_spec = unified_manager.resolve_node_spec(node_spec_str) + node_name, version_spec, _ = node_spec - # Best-effort uninstall via normal path - unified_manager.unified_uninstall(node_name, version_spec == 'unknown') + unified_manager.unified_uninstall(node_name, version_spec == 'unknown') + unified_manager.purge_node_state(node_name) - # Fallback: purge all state and directories regardless of categorization - # Handles categorization mismatch between cm_cli invocations (e.g. unknown→nightly) - unified_manager.purge_node_state(node_name) - - install_node(node_name, is_all=is_all, cnt_msg=cnt_msg, raise_on_fail=True) + install_node(node_name, is_all=is_all, cnt_msg=cnt_msg, raise_on_fail=True) def fix_node(node_spec_str, is_all=False, cnt_msg=''): diff --git a/comfyui_manager/common/git_helper.py b/comfyui_manager/common/git_helper.py index c8ae6cb2..46e7ad88 100644 --- a/comfyui_manager/common/git_helper.py +++ b/comfyui_manager/common/git_helper.py @@ -101,7 +101,11 @@ def gitclone(custom_nodes_path, url, target_hash=None, repo_path=None): repo_path = os.path.join(custom_nodes_path, repo_name) # Clone the repository from the remote URL - repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=GitProgress()) + # Disable tqdm progress when stderr is piped to avoid deadlock on Windows. + # When a parent process captures stderr via PIPE, tqdm output can fill the + # 4KB Windows pipe buffer, blocking GitPython's progress reader and git itself. + progress = GitProgress() if sys.stderr.isatty() else None + repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=progress) if target_hash is not None: print(f"CHECKOUT: {repo_name} [{target_hash}]")