diff --git a/__init__.py b/__init__.py
index b2e081eb..689259c7 100644
--- a/__init__.py
+++ b/__init__.py
@@ -55,7 +55,7 @@ sys.path.append('../..')
from torchvision.datasets.utils import download_url
# ensure .js
-print("### Loading: ComfyUI-Manager (V0.27)")
+print("### Loading: ComfyUI-Manager (V0.28)")
comfy_ui_required_revision = 1240
comfy_ui_revision = "Unknown"
@@ -236,9 +236,11 @@ print_comfyui_version()
# use subprocess to avoid file system lock by git (Windows)
-def __win_check_git_update(path, do_fetch=False):
+def __win_check_git_update(path, do_fetch=False, do_update=False):
if do_fetch:
command = [sys.executable, git_script_path, "--fetch", path]
+ elif do_update:
+ command = [sys.executable, git_script_path, "--pull", path]
else:
command = [sys.executable, git_script_path, "--check", path]
@@ -260,13 +262,18 @@ def __win_check_git_pull(path):
process.wait()
-def git_repo_has_updates(path, do_fetch=False):
+def git_repo_has_updates(path, do_fetch=False, do_update=False):
+ if do_fetch:
+ print(f"\rFetching: {path}", end='')
+ elif do_update:
+ print(f"\rUpdating: {path}", end='')
+
# Check if the path is a git repository
if not os.path.exists(os.path.join(path, '.git')):
raise ValueError('Not a git repository')
if platform.system() == "Windows":
- return __win_check_git_update(path, do_fetch)
+ return __win_check_git_update(path, do_fetch, do_update)
else:
# Fetch the latest commits from the remote repository
repo = git.Repo(path)
@@ -279,6 +286,12 @@ def git_repo_has_updates(path, do_fetch=False):
if do_fetch:
remote.fetch()
+ elif do_update:
+ try:
+ remote.pull(rebase=True)
+ repo.git.submodule('update', '--init', '--recursive')
+ except Exception as e:
+ print(f"Updating failed: '{path}'\n{e}")
# Get the current commit hash and the commit hash of the remote branch
commit_hash = repo.head.commit.hexsha
@@ -408,7 +421,7 @@ def get_model_path(data):
return os.path.join(base_model, data['filename'])
-def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True):
+def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do_update=False):
item['installed'] = 'None'
if item['install_type'] == 'git-clone' and len(item['files']) == 1:
@@ -416,7 +429,7 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True):
dir_path = os.path.join(custom_nodes_path, dir_name)
if os.path.exists(dir_path):
try:
- if do_update_check and git_repo_has_updates(dir_path, do_fetch):
+ if do_update_check and git_repo_has_updates(dir_path, do_fetch, do_update):
item['installed'] = 'Update'
else:
item['installed'] = 'True'
@@ -448,9 +461,23 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True):
item['installed'] = 'False'
-def check_custom_nodes_installed(json_obj, do_fetch=False, do_update_check=True):
+def check_custom_nodes_installed(json_obj, do_fetch=False, do_update_check=True, do_update=False):
+ if do_fetch:
+ print("Start fetching...")
+ elif do_update:
+ print("Start updating...")
+ elif do_update_check:
+ print("Start update check...")
+
for item in json_obj['custom_nodes']:
- check_a_custom_node_installed(item, do_fetch, do_update_check)
+ check_a_custom_node_installed(item, do_fetch, do_update_check, do_update)
+
+ if do_fetch:
+ print("\nFetch done.")
+ elif do_update:
+ print("\nUpdate done.")
+ elif do_update_check:
+ print("Update check done...")
@server.PromptServer.instance.routes.get("/customnode/getmappings")
@@ -487,6 +514,22 @@ async def fetch_updates(request):
return web.Response(status=400)
+@server.PromptServer.instance.routes.get("/customnode/update_all")
+async def update_all(request):
+ try:
+ if request.rel_url.query["mode"] == "local":
+ uri = local_db_custom_node_list
+ else:
+ uri = get_config()['channel_url'] + '/custom-node-list.json'
+
+ json_obj = await get_data(uri)
+ check_custom_nodes_installed(json_obj, do_update=True)
+
+ return web.Response(status=200)
+ except:
+ return web.Response(status=400)
+
+
@server.PromptServer.instance.routes.get("/customnode/getlist")
async def fetch_customnode_list(request):
if "skip_update" in request.rel_url.query and request.rel_url.query["skip_update"] == "true":
diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js
index b9501072..50bae9af 100644
--- a/js/comfyui-manager.js
+++ b/js/comfyui-manager.js
@@ -5,6 +5,7 @@ import {ComfyWidgets} from "../../scripts/widgets.js";
var update_comfyui_button = null;
var fetch_updates_button = null;
+var update_all_button = null;
var badge_mode = "none";
async function init_badge_mode() {
@@ -214,7 +215,7 @@ async function fetchUpdates(update_check_checkbox) {
const response = await api.fetchApi(`/customnode/fetch_updates?mode=${mode}`);
- if(response.status == 400) {
+ if(response.status != 200) {
app.ui.dialog.show('Failed to fetch updates.');
app.ui.dialog.element.style.zIndex = 9999;
return false;
@@ -244,6 +245,44 @@ async function fetchUpdates(update_check_checkbox) {
}
}
+async function updateAll(update_check_checkbox) {
+ let prev_text = update_all_button.innerText;
+ update_all_button.innerText = "Updating all...(ComfyUI)";
+ update_all_button.disabled = true;
+ update_all_button.style.backgroundColor = "gray";
+
+ try {
+ var mode = "url";
+ if(ManagerMenuDialog.instance.local_mode_checkbox.checked)
+ mode = "local";
+
+ update_all_button.innerText = "Updating all...";
+ const response1 = await api.fetchApi('/comfyui_manager/update_comfyui');
+ const response2 = await api.fetchApi(`/customnode/update_all?mode=${mode}`);
+
+ if(response1.status != 200 || response2.status != 200) {
+ app.ui.dialog.show('Failed to update ComfyUI or several extensions.
See terminal log.
');
+ app.ui.dialog.element.style.zIndex = 9999;
+ return false;
+ }
+
+ app.ui.dialog.show('ComfyUI and all extensions are already up-to-date with the latest versions.');
+ app.ui.dialog.element.style.zIndex = 9999;
+
+ return true;
+ }
+ catch(exception) {
+ app.ui.dialog.show(`Failed to update ComfyUI or several extensions / ${exception}`);
+ app.ui.dialog.element.style.zIndex = 9999;
+ return false;
+ }
+ finally {
+ update_all_button.disabled = false;
+ update_all_button.innerText = prev_text;
+ update_all_button.style.backgroundColor = "";
+ }
+}
+
async function install_model(target) {
if(ModelInstaller.instance) {
ModelInstaller.instance.startInstall(target);
@@ -1768,6 +1807,14 @@ class ManagerMenuDialog extends ComfyDialog {
() => fetchUpdates(this.update_check_checkbox)
});
+ update_all_button =
+ $el("button", {
+ type: "button",
+ textContent: "Update All",
+ onclick:
+ () => updateAll(this.update_check_checkbox)
+ });
+
// preview method
let preview_combo = document.createElement("select");
preview_combo.appendChild($el('option', {value:'auto', text:'Preview method: Auto'}, []));
@@ -1864,6 +1911,7 @@ class ManagerMenuDialog extends ComfyDialog {
}),
$el("br", {}, []),
+ update_all_button,
update_comfyui_button,
fetch_updates_button,