diff --git a/git_helper.py b/git_helper.py index f9cc661d..e79b43a6 100644 --- a/git_helper.py +++ b/git_helper.py @@ -154,14 +154,27 @@ def switch_to_default_branch(repo): repo.git.checkout(default_branch) return True except: + # try checkout master + # try checkout main if failed try: repo.git.checkout(repo.heads.master) + return True except: try: if remote_name is not None: repo.git.checkout('-b', 'master', f'{remote_name}/master') + return True except: - pass + try: + repo.git.checkout(repo.heads.main) + return True + except: + try: + if remote_name is not None: + repo.git.checkout('-b', 'main', f'{remote_name}/main') + return True + except: + pass print("[ComfyUI Manager] Failed to switch to the default branch") return False diff --git a/glob/git_utils.py b/glob/git_utils.py index 29946862..8785bb6d 100644 --- a/glob/git_utils.py +++ b/glob/git_utils.py @@ -53,7 +53,14 @@ def git_url(fullpath): def normalize_url(url) -> str: if 'github' in url or (GITHUB_ENDPOINT is not None and GITHUB_ENDPOINT in url): author = os.path.basename(os.path.dirname(url)) + + if author.startswith('git@github.com:'): + author = author.split(':')[1] + repo_name = os.path.basename(url) + if repo_name.endswith('.git'): + repo_name = repo_name[:-4] + url = f"https://github.com/{author}/{repo_name}" return url diff --git a/glob/manager_core.py b/glob/manager_core.py index 2a378fac..5d5614e1 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, 24, 1] +version_code = [3, 25] version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') @@ -538,6 +538,8 @@ class UnifiedManager: if node_package.is_disabled and node_package.is_unknown: url = git_utils.git_url(node_package.fullpath) + if url is not None: + url = git_utils.normalize_url(url) self.unknown_inactive_nodes[node_package.id] = (url, node_package.fullpath) if node_package.is_disabled and node_package.is_nightly: @@ -548,6 +550,8 @@ class UnifiedManager: if node_package.is_enabled and node_package.is_unknown: url = git_utils.git_url(node_package.fullpath) + if url is not None: + url = git_utils.normalize_url(url) self.unknown_active_nodes[node_package.id] = (url, node_package.fullpath) if node_package.is_from_cnr and node_package.is_disabled: @@ -1059,8 +1063,8 @@ class UnifiedManager: # update cache if version_spec == 'unknown': + self.unknown_active_nodes[node_id] = self.unknown_inactive_nodes[node_id][0], to_path del self.unknown_inactive_nodes[node_id] - self.unknown_active_nodes[node_id] = to_path return result.with_target(to_path) elif version_spec == 'nightly': del self.nightly_inactive_nodes[node_id] @@ -1401,7 +1405,7 @@ class UnifiedManager: res = self.repo_install(repo_url, to_path, instant_execution=instant_execution, no_deps=no_deps, return_postinstall=return_postinstall) if res.result: if version_spec == 'unknown': - self.unknown_active_nodes[node_id] = to_path + self.unknown_active_nodes[node_id] = repo_url, to_path elif version_spec == 'nightly': cnr_utils.generate_cnr_id(to_path, node_id) self.active_nodes[node_id] = 'nightly', to_path @@ -1577,6 +1581,7 @@ def write_config(): 'bypass_ssl': get_config()['bypass_ssl'], "file_logging": get_config()['file_logging'], 'component_policy': get_config()['component_policy'], + 'update_policy': get_config()['update_policy'], 'windows_selector_event_loop_policy': get_config()['windows_selector_event_loop_policy'], 'model_download_by_agent': get_config()['model_download_by_agent'], 'downgrade_blacklist': get_config()['downgrade_blacklist'], @@ -1615,6 +1620,7 @@ def read_config(): 'bypass_ssl': get_bool('bypass_ssl', False), 'file_logging': get_bool('file_logging', True), 'component_policy': default_conf.get('component_policy', 'workflow').lower(), + 'update_policy': default_conf.get('update_policy', 'stable-comfyui').lower(), 'windows_selector_event_loop_policy': get_bool('windows_selector_event_loop_policy', False), 'model_download_by_agent': get_bool('model_download_by_agent', False), 'downgrade_blacklist': default_conf.get('downgrade_blacklist', '').lower(), @@ -1637,6 +1643,7 @@ def read_config(): 'bypass_ssl': False, 'file_logging': True, 'component_policy': 'workflow', + 'update_policy': 'stable-comfyui', 'windows_selector_event_loop_policy': False, 'model_download_by_agent': False, 'downgrade_blacklist': '', @@ -1688,14 +1695,27 @@ def switch_to_default_branch(repo): repo.git.checkout(default_branch) return True except: + # try checkout master + # try checkout main if failed try: repo.git.checkout(repo.heads.master) + return True except: try: if remote_name is not None: repo.git.checkout('-b', 'master', f'{remote_name}/master') + return True except: - pass + try: + repo.git.checkout(repo.heads.main) + return True + except: + try: + if remote_name is not None: + repo.git.checkout('-b', 'main', f'{remote_name}/main') + return True + except: + pass print("[ComfyUI Manager] Failed to switch to the default branch") return False @@ -2347,6 +2367,32 @@ def gitclone_update(files, instant_execution=False, skip_script=False, msg_prefi return True +def update_to_stable_comfyui(repo_path): + try: + repo = git.Repo(repo_path) + repo.git.checkout(repo.heads.master) + versions, current_tag, _ = get_comfyui_versions(repo) + + if len(versions) == 0 or (len(versions) == 1 and versions[0] == 'nightly'): + logging.info("[ComfyUI-Manager] Unable to update to the stable ComfyUI version.") + return "fail", None + + if versions[0] == 'nightly': + latest_tag = versions[1] + else: + latest_tag = versions[0] + + if current_tag == latest_tag: + return "skip", None + else: + logging.info(f"[ComfyUI-Manager] Updating ComfyUI: {current_tag} -> {latest_tag}") + repo.git.checkout(latest_tag) + return 'updated', latest_tag + except: + traceback.print_exc() + return "fail", None + + def update_path(repo_path, instant_execution=False, no_deps=False): if not os.path.exists(os.path.join(repo_path, '.git')): return "fail" @@ -2354,9 +2400,12 @@ def update_path(repo_path, instant_execution=False, no_deps=False): # version check repo = git.Repo(repo_path) + is_switched = False if repo.head.is_detached: if not switch_to_default_branch(repo): return "fail" + else: + is_switched = True current_branch = repo.active_branch branch_name = current_branch.name @@ -2395,6 +2444,8 @@ def update_path(repo_path, instant_execution=False, no_deps=False): git_pull(repo_path) execute_install_script("ComfyUI", repo_path, instant_execution=instant_execution, no_deps=no_deps) return "updated" + elif is_switched: + return "updated" else: return "skipped" @@ -2705,9 +2756,6 @@ async def extract_nodes_from_workflow(filepath, mode='local', channel_url='defau if ext == 'https://github.com/comfyanonymous/ComfyUI': pass elif ext is not None: - if 'Fooocus' in ext: - print(f">> {node_name}") - used_exts.add(ext) else: unknown_nodes.add(node_name) @@ -3176,17 +3224,26 @@ async def check_need_to_migrate(): need_to_migrate = True -def get_comfyui_versions(): - repo = git.Repo(comfy_path) - versions = [x.name for x in repo.tags if x.name.startswith('v')] - versions.reverse() # nearest tag +def get_comfyui_versions(repo=None): + if repo is None: + repo = git.Repo(comfy_path) + try: + remote = get_remote_name(repo) + repo.remotes[remote].fetch() + except: + logging.error("[ComfyUI-Manager] Failed to fetch ComfyUI") + + versions = [x.name for x in repo.tags if x.name.startswith('v')] + + # nearest tag + versions = sorted(versions, key=lambda v: repo.git.log('-1', '--format=%ct', v), reverse=True) versions = versions[:4] current_tag = repo.git.describe('--tags') if current_tag not in versions: - versions = sorted(versions + [current_tag], reverse=True) + versions = sorted(versions + [current_tag], key=lambda v: repo.git.log('-1', '--format=%ct', v), reverse=True) versions = versions[:4] main_branch = repo.heads.master @@ -3199,16 +3256,16 @@ def get_comfyui_versions(): versions[0] = 'nightly' current_tag = 'nightly' - return versions, current_tag + return versions, current_tag, latest_tag def switch_comfyui(tag): repo = git.Repo(comfy_path) if tag == 'nightly': - repo.git.checkout('main') + repo.git.checkout('master') repo.remotes.origin.pull() - print("[ComfyUI-Manager] ComfyUI version is switched to the latest 'main' version") + print("[ComfyUI-Manager] ComfyUI version is switched to the latest 'master' version") else: repo.git.checkout(tag) print(f"[ComfyUI-Manager] ComfyUI version is switched to '{tag}'") diff --git a/glob/manager_server.py b/glob/manager_server.py index 6aa0c49d..2e462c09 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -187,6 +187,8 @@ set_preview_method(core.get_config()['preview_method']) def set_component_policy(mode): core.get_config()['component_policy'] = mode +def set_update_policy(mode): + core.get_config()['update_policy'] = mode def print_comfyui_version(): global comfy_ui_hash @@ -452,20 +454,29 @@ async def task_worker(): return {'msg':f"An error occurred while updating '{node_name}'."} - async def do_update_comfyui() -> str: + async def do_update_comfyui(is_stable) -> str: try: repo_path = os.path.dirname(folder_paths.__file__) - res = core.update_path(repo_path) - + latest_tag = None + if is_stable: + res, latest_tag = core.update_to_stable_comfyui(repo_path) + else: + res = core.update_path(repo_path) + if res == "fail": logging.error("ComfyUI update fail: The installed ComfyUI does not have a Git repository.") return "The installed ComfyUI does not have a Git repository." elif res == "updated": - logging.info("ComfyUI is updated.") - return "success" + if is_stable: + logging.info("ComfyUI is updated to latest stable version.") + return "success-stable-"+latest_tag + else: + logging.info("ComfyUI is updated to latest nightly version.") + return "success-nightly" else: # skipped logging.info("ComfyUI is up-to-date.") return "skip" + except Exception: traceback.print_exc() @@ -597,7 +608,7 @@ async def task_worker(): elif kind == 'update-main': msg = await do_update(item) elif kind == 'update-comfyui': - msg = await do_update_comfyui() + msg = await do_update_comfyui(item[1]) elif kind == 'fix': msg = await do_fix(item) elif kind == 'uninstall': @@ -1337,14 +1348,15 @@ async def update_custom_node(request): @routes.get("/manager/queue/update_comfyui") async def update_comfyui(request): - task_queue.put(("update-comfyui", ('comfyui',))) + is_stable = core.get_config()['update_policy'] != 'nightly-comfyui' + task_queue.put(("update-comfyui", ('comfyui', is_stable))) return web.Response(status=200) @routes.get("/comfyui_manager/comfyui_versions") async def comfyui_versions(request): try: - res, current = core.get_comfyui_versions() + res, current, latest = core.get_comfyui_versions() return web.json_response({'versions': res, 'current': current}, status=200, content_type='application/json') except Exception as e: logging.error(f"ComfyUI update fail: {e}", file=sys.stderr) @@ -1435,7 +1447,7 @@ async def preview_method(request): return web.Response(status=200) -@routes.get("/manager/component/policy") +@routes.get("/manager/policy/component") async def component_policy(request): if "value" in request.rel_url.query: set_component_policy(request.rel_url.query['value']) @@ -1446,6 +1458,17 @@ async def component_policy(request): return web.Response(status=200) +@routes.get("/manager/policy/update") +async def update_policy(request): + if "value" in request.rel_url.query: + set_update_policy(request.rel_url.query['value']) + core.write_config() + else: + return web.Response(text=core.get_config()['update_policy'], status=200) + + return web.Response(status=200) + + @routes.get("/manager/channel_url_list") async def channel_url_list(request): channels = core.get_channel_dict() diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index 4d070c32..6e854828 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -230,7 +230,7 @@ var update_all_button = null; var restart_stop_button = null; let share_option = 'all'; -var is_updating_all = false; +var is_updating = false; // copied style from https://github.com/pythongosssss/ComfyUI-Custom-Scripts @@ -477,6 +477,8 @@ async function updateComfyUI() { const response = await api.fetchApi('/manager/queue/update_comfyui'); showTerminal(); + + is_updating = true; await api.fetchApi('/manager/queue/start'); } @@ -605,8 +607,14 @@ function showVersionSelectorDialog(versions, current, onSelect) { } async function switchComfyUI() { + switch_comfyui_button.disabled = true; + switch_comfyui_button.style.backgroundColor = "gray"; + let res = await api.fetchApi(`/comfyui_manager/comfyui_versions`, { cache: "no-store" }); + switch_comfyui_button.disabled = false; + switch_comfyui_button.style.backgroundColor = ""; + if(res.status == 200) { let obj = await res.json(); @@ -694,11 +702,11 @@ async function onQueueStatus(event) { else if(event.detail.status == 'done') { reset_action_buttons(); - if(!is_updating_all) { + if(!is_updating) { return; } - is_updating_all = false; + is_updating = false; let success_list = []; let failed_list = []; @@ -721,19 +729,25 @@ async function onQueueStatus(event) { let msg = ""; - if(success_list.length == 0 && comfyui_state != 'success') { + if(success_list.length == 0 && !comfyui_state.startsWith('success')) { if(failed_list.length == 0) { - msg += "All custom nodes are already up to date."; + msg += "You are already up to date."; } } else { msg = "To apply the updates, you need to ComfyUI.