diff --git a/glob/manager_core.py b/glob/manager_core.py index 004ce556..598c71c9 100644 --- a/glob/manager_core.py +++ b/glob/manager_core.py @@ -42,7 +42,7 @@ import manager_downloader from node_package import InstalledNodePackage -version_code = [3, 27, 7] +version_code = [3, 27, 8] version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') @@ -1173,14 +1173,14 @@ class UnifiedManager: ver_and_path = self.active_nodes.get(node_id) if ver_and_path is not None and os.path.exists(ver_and_path[1]): - shutil.rmtree(ver_and_path[1]) + try_rmtree(node_id, ver_and_path[1]) result.items.append(ver_and_path) del self.active_nodes[node_id] # remove from nightly inactives fullpath = self.nightly_inactive_nodes.get(node_id) if fullpath is not None and os.path.exists(fullpath): - shutil.rmtree(fullpath) + try_rmtree(node_id, fullpath) result.items.append(('nightly', fullpath)) del self.nightly_inactive_nodes[node_id] @@ -1188,7 +1188,7 @@ class UnifiedManager: ver_map = self.cnr_inactive_nodes.get(node_id) if ver_map is not None: for key, fullpath in ver_map.items(): - shutil.rmtree(fullpath) + try_rmtree(node_id, fullpath) result.items.append((key, fullpath)) del self.cnr_inactive_nodes[node_id] @@ -1750,18 +1750,29 @@ def switch_to_default_branch(repo): return False +def reserve_script(repo_path, install_cmds): + if not os.path.exists(manager_startup_script_path): + os.makedirs(manager_startup_script_path) + + script_path = os.path.join(manager_startup_script_path, "install-scripts.txt") + with open(script_path, "a") as file: + obj = [repo_path] + install_cmds + file.write(f"{obj}\n") + + +def try_rmtree(title, fullpath): + try: + shutil.rmtree(fullpath) + except Exception as e: + logging.warning(f"[ComfyUI-Manager] An error occurred while deleting '{fullpath}', so it has been scheduled for deletion upon restart.\nEXCEPTION: {e}") + reserve_script(title, ["#LAZY-DELETE-NODEPACK", fullpath]) + + def try_install_script(url, repo_path, install_cmd, instant_execution=False): if not instant_execution and ( (len(install_cmd) > 0 and install_cmd[0].startswith('#')) or platform.system() == "Windows" or get_config()['always_lazy_install'] ): - if not os.path.exists(manager_startup_script_path): - os.makedirs(manager_startup_script_path) - - script_path = os.path.join(manager_startup_script_path, "install-scripts.txt") - with open(script_path, "a") as file: - obj = [repo_path] + install_cmd - file.write(f"{obj}\n") - + reserve_script(repo_path, install_cmd) return True else: if len(install_cmd) == 5 and install_cmd[2:4] == ['pip', 'install']: diff --git a/prestartup_script.py b/prestartup_script.py index 1d914612..f3a4cc4c 100644 --- a/prestartup_script.py +++ b/prestartup_script.py @@ -1,4 +1,5 @@ import os +import shutil import subprocess import sys import atexit @@ -695,13 +696,44 @@ def execute_migration(moves): shutil.move(x[0], x[1]) print(f"[ComfyUI-Manager] MIGRATION: '{x[0]}' -> '{x[1]}'") + script_executed = False -# Check if script_list_path exists -if os.path.exists(script_list_path): +def execute_startup_script(): + global script_executed print("\n#######################################################################") print("[ComfyUI-Manager] Starting dependency installation/(de)activation for the extension\n") + custom_nodelist_cache = None + + def get_custom_node_paths(): + nonlocal custom_nodelist_cache + if custom_nodelist_cache is None: + custom_nodelist_cache = set() + for base in folder_paths.get_folder_paths('custom_nodes'): + for x in os.listdir(base): + fullpath = os.path.join(base, x) + if os.path.isdir(fullpath): + custom_nodelist_cache.add(fullpath) + + return custom_nodelist_cache + + def execute_lazy_delete(path): + # Validate to prevent arbitrary paths from being deleted + if path not in get_custom_node_paths(): + logging.error(f"## ComfyUI-Manager: The scheduled '{path}' is not a custom node path, so the deletion has been canceled.") + return + + if not os.path.exists(path): + logging.info(f"## ComfyUI-Manager: SKIP-DELETE => '{path}' (already deleted)") + return + + try: + shutil.rmtree(path) + logging.info(f"## ComfyUI-Manager: DELETE => '{path}'") + except Exception as e: + logging.error(f"## ComfyUI-Manager: Failed to delete '{path}' ({e})") + executed = set() # Read each line from the file and convert it to a list using eval with open(script_list_path, 'r', encoding="UTF-8", errors="ignore") as file: @@ -725,6 +757,9 @@ if os.path.exists(script_list_path): elif script[1] == "#LAZY-MIGRATION": execute_migration(script[2]) + elif script[1] == "#LAZY-DELETE-NODEPACK": + execute_lazy_delete(script[2]) + elif os.path.exists(script[0]): if script[1] == "#FORCE": del script[1] @@ -733,7 +768,7 @@ if os.path.exists(script_list_path): continue print(f"\n## ComfyUI-Manager: EXECUTE => {script[1:]}") - print(f"\n## Execute install/(de)activation script for '{script[0]}'") + print(f"\n## Execute management script for '{script[0]}'") new_env = os.environ.copy() if 'COMFYUI_FOLDERS_BASE_PATH' not in new_env: @@ -741,12 +776,12 @@ if os.path.exists(script_list_path): exit_code = process_wrap(script[1:], script[0], env=new_env) if exit_code != 0: - print(f"install/(de)activation script failed: {script[0]}") + print(f"management script failed: {script[0]}") else: print(f"\n## ComfyUI-Manager: CANCELED => {script[1:]}") except Exception as e: - print(f"[ERROR] Failed to execute install/(de)activation script: {line} / {e}") + print(f"[ERROR] Failed to execute management script: {line} / {e}") # Remove the script_list_path file if os.path.exists(script_list_path): @@ -756,6 +791,12 @@ if os.path.exists(script_list_path): print("\n[ComfyUI-Manager] Startup script completed.") print("#######################################################################\n") + +# Check if script_list_path exists +if os.path.exists(script_list_path): + execute_startup_script() + + pip_fixer.fix_broken() del processed_install diff --git a/pyproject.toml b/pyproject.toml index 57be5332..fb6ecfdb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-manager" description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI." -version = "3.27.7" +version = "3.27.8" license = { file = "LICENSE.txt" } dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]