Skip to content

Commit 41ab628

Browse files
committed
fix(git_helper): Windows subprocess crash fix — reinstall URL handling + tqdm pipe deadlock
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.
1 parent 099aed1 commit 41ab628

2 files changed

Lines changed: 25 additions & 10 deletions

File tree

cm_cli/__main__.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,29 @@ def install_node(node_spec_str, is_all=False, cnt_msg='', **kwargs):
238238

239239

240240
def reinstall_node(node_spec_str, is_all=False, cnt_msg=''):
241-
node_spec = unified_manager.resolve_node_spec(node_spec_str)
242-
243-
node_name, version_spec, _ = node_spec
241+
if core.is_valid_url(node_spec_str):
242+
# URL-based: resolve_node_spec returns the full URL as node_name,
243+
# but internal dicts are keyed by repo basename or cnr_id.
244+
url = node_spec_str.rstrip('/')
245+
cnr = unified_manager.get_cnr_by_repo(url)
246+
if cnr:
247+
node_id = cnr['id']
248+
unified_manager.unified_uninstall(node_id, False)
249+
unified_manager.purge_node_state(node_id)
250+
else:
251+
repo_name = os.path.splitext(os.path.basename(url))[0]
252+
unified_manager.unified_uninstall(repo_name, True)
253+
unified_manager.purge_node_state(repo_name)
244254

245-
# Best-effort uninstall via normal path
246-
unified_manager.unified_uninstall(node_name, version_spec == 'unknown')
255+
install_node(node_spec_str, is_all=is_all, cnt_msg=cnt_msg, raise_on_fail=True)
256+
else:
257+
node_spec = unified_manager.resolve_node_spec(node_spec_str)
258+
node_name, version_spec, _ = node_spec
247259

248-
# Fallback: purge all state and directories regardless of categorization
249-
# Handles categorization mismatch between cm_cli invocations (e.g. unknown→nightly)
250-
unified_manager.purge_node_state(node_name)
260+
unified_manager.unified_uninstall(node_name, version_spec == 'unknown')
261+
unified_manager.purge_node_state(node_name)
251262

252-
install_node(node_name, is_all=is_all, cnt_msg=cnt_msg, raise_on_fail=True)
263+
install_node(node_name, is_all=is_all, cnt_msg=cnt_msg, raise_on_fail=True)
253264

254265

255266
def fix_node(node_spec_str, is_all=False, cnt_msg=''):

comfyui_manager/common/git_helper.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ def gitclone(custom_nodes_path, url, target_hash=None, repo_path=None):
101101
repo_path = os.path.join(custom_nodes_path, repo_name)
102102

103103
# Clone the repository from the remote URL
104-
repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=GitProgress())
104+
# Disable tqdm progress when stderr is piped to avoid deadlock on Windows.
105+
# When a parent process captures stderr via PIPE, tqdm output can fill the
106+
# 4KB Windows pipe buffer, blocking GitPython's progress reader and git itself.
107+
progress = GitProgress() if sys.stderr.isatty() else None
108+
repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=progress)
105109

106110
if target_hash is not None:
107111
print(f"CHECKOUT: {repo_name} [{target_hash}]")

0 commit comments

Comments
 (0)