diff --git a/README.md b/README.md index f6ef260..2e8c29c 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ NODE_CLASS_MAPPINGS.update({ - [x] Specification scanner - [x] workflow download -> workflow gallery - [x] Search extension by node name -> [ltdrdata.github.io](https://ltdrdata.github.io) -- [ ] installation from git url +- [x] installation from git url # Disclaimer diff --git a/__init__.py b/__init__.py index 40943d8..6539acb 100644 --- a/__init__.py +++ b/__init__.py @@ -11,8 +11,9 @@ import subprocess # don't remove this from tqdm.auto import tqdm import concurrent import ssl +from urllib.parse import urlparse -version = "V0.41" +version = "V0.42" print(f"### Loading: ComfyUI-Manager ({version})") @@ -990,10 +991,20 @@ class GitProgress(RemoteProgress): self.pbar.pos = 0 self.pbar.refresh() +def is_valid_url(url): + try: + result = urlparse(url) + return all([result.scheme, result.netloc]) + except ValueError: + return False def gitclone_install(files): print(f"install: {files}") for url in files: + if not is_valid_url(url): + print(f"Invalid git url: '{url}'") + return False + if url.endswith("/"): url = url[:-1] try: @@ -1003,7 +1014,9 @@ def gitclone_install(files): # Clone the repository from the remote URL if platform.system() == 'Windows': - run_script([sys.executable, git_script_path, "--clone", custom_nodes_path, url]) + res = run_script([sys.executable, git_script_path, "--clone", custom_nodes_path, url]) + if res != 0: + return False else: repo = git.Repo.clone_from(url, repo_path, recursive=True, progress=GitProgress()) repo.git.clear_cache() @@ -1196,6 +1209,20 @@ async def install_custom_node(request): return web.Response(status=400) +@server.PromptServer.instance.routes.get("/customnode/install/git_url") +async def install_custom_node_git_url(request): + res = False + if "url" in request.rel_url.query: + url = request.rel_url.query['url'] + res = gitclone_install([url]) + + if res: + print(f"After restarting ComfyUI, please refresh the browser.") + return web.Response(status=200) + + return web.Response(status=400) + + @server.PromptServer.instance.routes.post("/customnode/uninstall") async def uninstall_custom_node(request): json_data = await request.json() diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index 4a227d2..d4ddf46 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -5,7 +5,7 @@ import { CustomNodesInstaller } from "./custom-nodes-downloader.js"; import { AlternativesInstaller } from "./a1111-alter-downloader.js"; import { SnapshotManager } from "./snapshot.js"; import { ModelInstaller } from "./model-downloader.js"; -import { manager_instance, setManagerInstance } from "./common.js"; +import { manager_instance, setManagerInstance, install_via_git_url } from "./common.js"; var style = document.createElement('style'); style.innerHTML = ` @@ -372,6 +372,17 @@ class ManagerMenuDialog extends ComfyDialog { SnapshotManager.instance.show(); } }), + $el("button", { + type: "button", + textContent: "Install via Git URL", + onclick: () => { + var url = prompt("Please enter the URL of the Git repository to install", ""); + + if (url !== null) { + install_via_git_url(url); + } + } + }), ]; } diff --git a/js/common.js b/js/common.js index b556269..175522d 100644 --- a/js/common.js +++ b/js/common.js @@ -59,4 +59,35 @@ export var manager_instance = null; export function setManagerInstance(obj) { manager_instance = obj; +} + +function isValidURL(url) { + const pattern = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/; + return pattern.test(url); +} + +export async function install_via_git_url(url) { + if(!url) { + return; + } + + if(!isValidURL(url)) { + app.ui.dialog.show(`Invalid Git url '${url}'`); + app.ui.dialog.element.style.zIndex = 10010; + return; + } + + app.ui.dialog.show(`Wait...

Installing '${url}'`); + app.ui.dialog.element.style.zIndex = 10010; + + const res = await api.fetchApi(`/customnode/install/git_url?url=${url}`); + + if(res.status == 200) { + app.ui.dialog.show(`'${url}' is installed
To apply the installed/disabled/enabled custom node, please restart ComfyUI.`); + app.ui.dialog.element.style.zIndex = 10010; + } + else { + app.ui.dialog.show(`Failed to install '${url}'
See terminal log.`); + app.ui.dialog.element.style.zIndex = 10010; + } } \ No newline at end of file