Dr.Lt.Data
7 months ago
3 changed files with 1022 additions and 1005 deletions
@ -0,0 +1,834 @@
|
||||
import os |
||||
import sys |
||||
import subprocess |
||||
import re |
||||
import shutil |
||||
import configparser |
||||
import platform |
||||
from datetime import datetime |
||||
import git |
||||
from git.remote import RemoteProgress |
||||
from urllib.parse import urlparse |
||||
from tqdm.auto import tqdm |
||||
import aiohttp |
||||
import threading |
||||
import json |
||||
import time |
||||
|
||||
glob_path = os.path.join(os.path.dirname(__file__), "glob") |
||||
sys.path.append(glob_path) |
||||
|
||||
import cm_global |
||||
from manager_util import * |
||||
|
||||
comfyui_manager_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) |
||||
custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, '..')) |
||||
channel_list_path = os.path.join(comfyui_manager_path, 'channels.list') |
||||
config_path = os.path.join(custom_nodes_path, "config.ini") |
||||
startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts") |
||||
git_script_path = os.path.join(custom_nodes_path, "git_helper.py") |
||||
cache_dir = os.path.join(comfyui_manager_path, '.cache') |
||||
cached_config = None |
||||
js_path = None |
||||
|
||||
comfy_ui_required_revision = 1930 |
||||
comfy_ui_required_commit_datetime = datetime(2024, 1, 24, 0, 0, 0) |
||||
|
||||
comfy_ui_revision = "Unknown" |
||||
comfy_ui_commit_datetime = datetime(1900, 1, 1, 0, 0, 0) |
||||
|
||||
|
||||
cache_lock = threading.Lock() |
||||
|
||||
|
||||
channel_dict = None |
||||
channel_list = None |
||||
pip_map = None |
||||
|
||||
|
||||
def remap_pip_package(pkg): |
||||
if pkg in cm_global.pip_overrides: |
||||
res = cm_global.pip_overrides[pkg] |
||||
print(f"[ComfyUI-Manager] '{pkg}' is remapped to '{res}'") |
||||
return res |
||||
else: |
||||
return pkg |
||||
|
||||
|
||||
def get_installed_packages(): |
||||
global pip_map |
||||
|
||||
if pip_map is None: |
||||
try: |
||||
result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True) |
||||
|
||||
pip_map = {} |
||||
for line in result.split('\n'): |
||||
x = line.strip() |
||||
if x: |
||||
y = line.split() |
||||
if y[0] == 'Package' or y[0].startswith('-'): |
||||
continue |
||||
|
||||
pip_map[y[0]] = y[1] |
||||
except subprocess.CalledProcessError as e: |
||||
print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.") |
||||
return set() |
||||
|
||||
return pip_map |
||||
|
||||
|
||||
def clear_pip_cache(): |
||||
global pip_map |
||||
pip_map = None |
||||
|
||||
|
||||
def is_blacklisted(name): |
||||
name = name.strip() |
||||
|
||||
pattern = r'([^<>!=]+)([<>!=]=?)(.*)' |
||||
match = re.search(pattern, name) |
||||
|
||||
if match: |
||||
name = match.group(1) |
||||
|
||||
if name in cm_global.pip_downgrade_blacklist: |
||||
pips = get_installed_packages() |
||||
|
||||
if match is None: |
||||
if name in pips: |
||||
return True |
||||
elif match.group(2) in ['<=', '==', '<']: |
||||
if name in pips: |
||||
if StrictVersion(pips[name]) >= StrictVersion(match.group(3)): |
||||
return True |
||||
|
||||
return False |
||||
|
||||
|
||||
def get_channel_dict(): |
||||
global channel_dict |
||||
|
||||
if channel_dict is None: |
||||
channel_dict = {} |
||||
|
||||
if not os.path.exists(channel_list_path): |
||||
shutil.copy(channel_list_path+'.template', channel_list_path) |
||||
|
||||
with open(os.path.join(comfyui_manager_path, 'channels.list'), 'r') as file: |
||||
channels = file.read() |
||||
for x in channels.split('\n'): |
||||
channel_info = x.split("::") |
||||
if len(channel_info) == 2: |
||||
channel_dict[channel_info[0]] = channel_info[1] |
||||
|
||||
return channel_dict |
||||
|
||||
|
||||
def get_channel_list(): |
||||
global channel_list |
||||
|
||||
if channel_list is None: |
||||
channel_list = [] |
||||
for k, v in get_channel_dict().items(): |
||||
channel_list.append(f"{k}::{v}") |
||||
|
||||
return channel_list |
||||
|
||||
|
||||
class ManagerFuncs: |
||||
def __init__(self): |
||||
pass |
||||
|
||||
def get_current_preview_method(self): |
||||
return "none" |
||||
|
||||
def run_script(self, cmd, cwd='.'): |
||||
if len(cmd) > 0 and cmd[0].startswith("#"): |
||||
print(f"[ComfyUI-Manager] Unexpected behavior: `{cmd}`") |
||||
return 0 |
||||
|
||||
out = subprocess.check_call(cmd, cwd=cwd) |
||||
print(out) |
||||
|
||||
return 0 |
||||
|
||||
|
||||
manager_funcs = ManagerFuncs() |
||||
|
||||
|
||||
def write_config(): |
||||
config = configparser.ConfigParser() |
||||
config['default'] = { |
||||
'preview_method': manager_funcs.get_current_preview_method(), |
||||
'badge_mode': get_config()['badge_mode'], |
||||
'git_exe': get_config()['git_exe'], |
||||
'channel_url': get_config()['channel_url'], |
||||
'share_option': get_config()['share_option'], |
||||
'bypass_ssl': get_config()['bypass_ssl'], |
||||
"file_logging": get_config()['file_logging'], |
||||
'default_ui': get_config()['default_ui'], |
||||
'component_policy': get_config()['component_policy'], |
||||
'double_click_policy': get_config()['double_click_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'] |
||||
} |
||||
with open(config_path, 'w') as configfile: |
||||
config.write(configfile) |
||||
|
||||
|
||||
def read_config(): |
||||
try: |
||||
config = configparser.ConfigParser() |
||||
config.read(config_path) |
||||
default_conf = config['default'] |
||||
|
||||
return { |
||||
'preview_method': default_conf['preview_method'] if 'preview_method' in default_conf else manager_funcs.get_current_preview_method(), |
||||
'badge_mode': default_conf['badge_mode'] if 'badge_mode' in default_conf else 'none', |
||||
'git_exe': default_conf['git_exe'] if 'git_exe' in default_conf else '', |
||||
'channel_url': default_conf['channel_url'] if 'channel_url' in default_conf else 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main', |
||||
'share_option': default_conf['share_option'] if 'share_option' in default_conf else 'all', |
||||
'bypass_ssl': default_conf['bypass_ssl'] if 'bypass_ssl' in default_conf else False, |
||||
'file_logging': default_conf['file_logging'] if 'file_logging' in default_conf else True, |
||||
'default_ui': default_conf['default_ui'] if 'default_ui' in default_conf else 'none', |
||||
'component_policy': default_conf['component_policy'] if 'component_policy' in default_conf else 'workflow', |
||||
'double_click_policy': default_conf['double_click_policy'] if 'double_click_policy' in default_conf else 'copy-all', |
||||
'windows_selector_event_loop_policy': default_conf['windows_selector_event_loop_policy'] if 'windows_selector_event_loop_policy' in default_conf else False, |
||||
'model_download_by_agent': default_conf['model_download_by_agent'] if 'model_download_by_agent' in default_conf else False, |
||||
'downgrade_blacklist': default_conf['downgrade_blacklist'] if 'downgrade_blacklist' in default_conf else '', |
||||
} |
||||
|
||||
except Exception: |
||||
return { |
||||
'preview_method': manager_funcs.get_current_preview_method(), |
||||
'badge_mode': 'none', |
||||
'git_exe': '', |
||||
'channel_url': 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main', |
||||
'share_option': 'all', |
||||
'bypass_ssl': False, |
||||
'file_logging': True, |
||||
'default_ui': 'none', |
||||
'component_policy': 'workflow', |
||||
'double_click_policy': 'copy-all', |
||||
'windows_selector_event_loop_policy': False, |
||||
'model_download_by_agent': False, |
||||
'downgrade_blacklist': '' |
||||
} |
||||
|
||||
|
||||
def get_config(): |
||||
global cached_config |
||||
|
||||
if cached_config is None: |
||||
cached_config = read_config() |
||||
|
||||
return cached_config |
||||
|
||||
|
||||
def switch_to_default_branch(repo): |
||||
show_result = repo.git.remote("show", "origin") |
||||
matches = re.search(r"\s*HEAD branch:\s*(.*)", show_result) |
||||
if matches: |
||||
default_branch = matches.group(1) |
||||
repo.git.checkout(default_branch) |
||||
|
||||
|
||||
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" and comfy_ui_commit_datetime.date() >= comfy_ui_required_commit_datetime.date())): |
||||
if not os.path.exists(startup_script_path): |
||||
os.makedirs(startup_script_path) |
||||
|
||||
script_path = os.path.join(startup_script_path, "install-scripts.txt") |
||||
with open(script_path, "a") as file: |
||||
obj = [repo_path] + install_cmd |
||||
file.write(f"{obj}\n") |
||||
|
||||
return True |
||||
else: |
||||
if len(install_cmd) == 5 and install_cmd[2:4] == ['pip', 'install']: |
||||
if is_blacklisted(install_cmd[4]): |
||||
print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'") |
||||
return True |
||||
|
||||
print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}") |
||||
code = manager_funcs.run_script(install_cmd, cwd=repo_path) |
||||
|
||||
if platform.system() == "Windows": |
||||
try: |
||||
if comfy_ui_commit_datetime.date() < comfy_ui_required_commit_datetime.date(): |
||||
print("\n\n###################################################################") |
||||
print(f"[WARN] ComfyUI-Manager: Your ComfyUI version ({comfy_ui_revision})[{comfy_ui_commit_datetime.date()}] is too old. Please update to the latest version.") |
||||
print(f"[WARN] The extension installation feature may not work properly in the current installed ComfyUI version on Windows environment.") |
||||
print("###################################################################\n\n") |
||||
except: |
||||
pass |
||||
|
||||
if code != 0: |
||||
if url is None: |
||||
url = os.path.dirname(repo_path) |
||||
print(f"install script failed: {url}") |
||||
return False |
||||
|
||||
|
||||
# use subprocess to avoid file system lock by git (Windows) |
||||
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] |
||||
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
output, _ = process.communicate() |
||||
output = output.decode('utf-8').strip() |
||||
|
||||
if 'detected dubious' in output: |
||||
# fix and try again |
||||
safedir_path = path.replace('\\', '/') |
||||
try: |
||||
print(f"[ComfyUI-Manager] Try fixing 'dubious repository' error on '{safedir_path}' repo") |
||||
process = subprocess.Popen(['git', 'config', '--global', '--add', 'safe.directory', safedir_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
output, _ = process.communicate() |
||||
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
output, _ = process.communicate() |
||||
output = output.decode('utf-8').strip() |
||||
except Exception: |
||||
print(f'[ComfyUI-Manager] failed to fixing') |
||||
|
||||
if 'detected dubious' in output: |
||||
print(f'\n[ComfyUI-Manager] Failed to fixing repository setup. Please execute this command on cmd: \n' |
||||
f'-----------------------------------------------------------------------------------------\n' |
||||
f'git config --global --add safe.directory "{safedir_path}"\n' |
||||
f'-----------------------------------------------------------------------------------------\n') |
||||
|
||||
if do_update: |
||||
if "CUSTOM NODE PULL: Success" in output: |
||||
process.wait() |
||||
print(f"\rUpdated: {path}") |
||||
return True, True # updated |
||||
elif "CUSTOM NODE PULL: None" in output: |
||||
process.wait() |
||||
return False, True # there is no update |
||||
else: |
||||
print(f"\rUpdate error: {path}") |
||||
process.wait() |
||||
return False, False # update failed |
||||
else: |
||||
if "CUSTOM NODE CHECK: True" in output: |
||||
process.wait() |
||||
return True, True |
||||
elif "CUSTOM NODE CHECK: False" in output: |
||||
process.wait() |
||||
return False, True |
||||
else: |
||||
print(f"\rFetch error: {path}") |
||||
print(f"\n{output}\n") |
||||
process.wait() |
||||
return False, True |
||||
|
||||
|
||||
def __win_check_git_pull(path): |
||||
command = [sys.executable, git_script_path, "--pull", path] |
||||
process = subprocess.Popen(command) |
||||
process.wait() |
||||
|
||||
|
||||
def execute_install_script(url, repo_path, lazy_mode=False): |
||||
install_script_path = os.path.join(repo_path, "install.py") |
||||
requirements_path = os.path.join(repo_path, "requirements.txt") |
||||
|
||||
if lazy_mode: |
||||
install_cmd = ["#LAZY-INSTALL-SCRIPT", sys.executable] |
||||
try_install_script(url, repo_path, install_cmd) |
||||
else: |
||||
if os.path.exists(requirements_path): |
||||
print("Install: pip packages") |
||||
with open(requirements_path, "r") as requirements_file: |
||||
for line in requirements_file: |
||||
package_name = remap_pip_package(line.strip()) |
||||
if package_name: |
||||
install_cmd = [sys.executable, "-m", "pip", "install", package_name] |
||||
if package_name.strip() != "": |
||||
try_install_script(url, repo_path, install_cmd) |
||||
|
||||
if os.path.exists(install_script_path): |
||||
print(f"Install: install script") |
||||
install_cmd = [sys.executable, "install.py"] |
||||
try_install_script(url, repo_path, install_cmd) |
||||
|
||||
return True |
||||
|
||||
|
||||
def git_repo_has_updates(path, do_fetch=False, do_update=False): |
||||
if do_fetch: |
||||
print(f"\x1b[2K\rFetching: {path}", end='') |
||||
elif do_update: |
||||
print(f"\x1b[2K\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": |
||||
updated, success = __win_check_git_update(path, do_fetch, do_update) |
||||
if updated and success: |
||||
execute_install_script(None, path, lazy_mode=True) |
||||
return updated, success |
||||
else: |
||||
# Fetch the latest commits from the remote repository |
||||
repo = git.Repo(path) |
||||
|
||||
current_branch = repo.active_branch |
||||
branch_name = current_branch.name |
||||
|
||||
remote_name = 'origin' |
||||
remote = repo.remote(name=remote_name) |
||||
|
||||
# Get the current commit hash |
||||
commit_hash = repo.head.commit.hexsha |
||||
|
||||
if do_fetch or do_update: |
||||
remote.fetch() |
||||
|
||||
if do_update: |
||||
if repo.head.is_detached: |
||||
switch_to_default_branch(repo) |
||||
|
||||
remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha |
||||
|
||||
if commit_hash == remote_commit_hash: |
||||
repo.close() |
||||
return False, True |
||||
|
||||
try: |
||||
remote.pull() |
||||
repo.git.submodule('update', '--init', '--recursive') |
||||
new_commit_hash = repo.head.commit.hexsha |
||||
|
||||
if commit_hash != new_commit_hash: |
||||
execute_install_script(None, path) |
||||
print(f"\x1b[2K\rUpdated: {path}") |
||||
return True, True |
||||
else: |
||||
return False, False |
||||
|
||||
except Exception as e: |
||||
print(f"\nUpdating failed: {path}\n{e}", file=sys.stderr) |
||||
return False, False |
||||
|
||||
if repo.head.is_detached: |
||||
repo.close() |
||||
return True, True |
||||
|
||||
# Get commit hash of the remote branch |
||||
current_branch = repo.active_branch |
||||
branch_name = current_branch.name |
||||
|
||||
remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha |
||||
|
||||
# Compare the commit hashes to determine if the local repository is behind the remote repository |
||||
if commit_hash != remote_commit_hash: |
||||
# Get the commit dates |
||||
commit_date = repo.head.commit.committed_datetime |
||||
remote_commit_date = repo.refs[f'{remote_name}/{branch_name}'].object.committed_datetime |
||||
|
||||
# Compare the commit dates to determine if the local repository is behind the remote repository |
||||
if commit_date < remote_commit_date: |
||||
repo.close() |
||||
return True, True |
||||
|
||||
repo.close() |
||||
|
||||
return False, True |
||||
|
||||
|
||||
class GitProgress(RemoteProgress): |
||||
def __init__(self): |
||||
super().__init__() |
||||
self.pbar = tqdm() |
||||
|
||||
def update(self, op_code, cur_count, max_count=None, message=''): |
||||
self.pbar.total = max_count |
||||
self.pbar.n = cur_count |
||||
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: |
||||
print(f"Download: git clone '{url}'") |
||||
repo_name = os.path.splitext(os.path.basename(url))[0] |
||||
repo_path = os.path.join(custom_nodes_path, repo_name) |
||||
|
||||
# Clone the repository from the remote URL |
||||
if platform.system() == 'Windows': |
||||
res = manager_funcs.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() |
||||
repo.close() |
||||
|
||||
if not execute_install_script(url, repo_path): |
||||
return False |
||||
|
||||
except Exception as e: |
||||
print(f"Install(git-clone) error: {url} / {e}", file=sys.stderr) |
||||
return False |
||||
|
||||
print("Installation was successful.") |
||||
return True |
||||
|
||||
|
||||
def git_pull(path): |
||||
# Check if the path is a git repository |
||||
if not os.path.exists(os.path.join(path, '.git')): |
||||
raise ValueError('Not a git repository') |
||||
|
||||
# Pull the latest changes from the remote repository |
||||
if platform.system() == "Windows": |
||||
return __win_check_git_pull(path) |
||||
else: |
||||
repo = git.Repo(path) |
||||
|
||||
if repo.is_dirty(): |
||||
repo.git.stash() |
||||
|
||||
if repo.head.is_detached: |
||||
switch_to_default_branch(repo) |
||||
|
||||
current_branch = repo.active_branch |
||||
remote_name = current_branch.tracking_branch().remote_name |
||||
remote = repo.remote(name=remote_name) |
||||
|
||||
remote.pull() |
||||
repo.git.submodule('update', '--init', '--recursive') |
||||
|
||||
repo.close() |
||||
|
||||
return True |
||||
|
||||
|
||||
async def get_data(uri, silent=False): |
||||
if not silent: |
||||
print(f"FETCH DATA from: {uri}") |
||||
|
||||
if uri.startswith("http"): |
||||
async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session: |
||||
async with session.get(uri) as resp: |
||||
json_text = await resp.text() |
||||
else: |
||||
with cache_lock: |
||||
with open(uri, "r", encoding="utf-8") as f: |
||||
json_text = f.read() |
||||
|
||||
json_obj = json.loads(json_text) |
||||
return json_obj |
||||
|
||||
|
||||
def simple_hash(input_string): |
||||
hash_value = 0 |
||||
for char in input_string: |
||||
hash_value = (hash_value * 31 + ord(char)) % (2**32) |
||||
|
||||
return hash_value |
||||
|
||||
|
||||
def is_file_created_within_one_day(file_path): |
||||
if not os.path.exists(file_path): |
||||
return False |
||||
|
||||
file_creation_time = os.path.getctime(file_path) |
||||
current_time = datetime.now().timestamp() |
||||
time_difference = current_time - file_creation_time |
||||
|
||||
return time_difference <= 86400 |
||||
|
||||
|
||||
async def get_data_by_mode(mode, filename): |
||||
try: |
||||
if mode == "local": |
||||
uri = os.path.join(comfyui_manager_path, filename) |
||||
json_obj = await get_data(uri) |
||||
else: |
||||
uri = get_config()['channel_url'] + '/' + filename |
||||
cache_uri = str(simple_hash(uri))+'_'+filename |
||||
cache_uri = os.path.join(cache_dir, cache_uri) |
||||
|
||||
if mode == "cache": |
||||
if is_file_created_within_one_day(cache_uri): |
||||
json_obj = await get_data(cache_uri) |
||||
else: |
||||
json_obj = await get_data(uri) |
||||
with cache_lock: |
||||
with open(cache_uri, "w", encoding='utf-8') as file: |
||||
json.dump(json_obj, file, indent=4, sort_keys=True) |
||||
else: |
||||
uri = get_config()['channel_url'] + '/' + filename |
||||
json_obj = await get_data(uri) |
||||
with cache_lock: |
||||
with open(cache_uri, "w", encoding='utf-8') as file: |
||||
json.dump(json_obj, file, indent=4, sort_keys=True) |
||||
except Exception as e: |
||||
print(f"[ComfyUI-Manager] Due to a network error, switching to local mode.\n=> {filename}\n=> {e}") |
||||
uri = os.path.join(comfyui_manager_path, filename) |
||||
json_obj = await get_data(uri) |
||||
|
||||
return json_obj |
||||
|
||||
|
||||
def gitclone_fix(files): |
||||
print(f"Try fixing: {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: |
||||
repo_name = os.path.splitext(os.path.basename(url))[0] |
||||
repo_path = os.path.join(custom_nodes_path, repo_name) |
||||
|
||||
if not execute_install_script(url, repo_path): |
||||
return False |
||||
|
||||
except Exception as e: |
||||
print(f"Install(git-clone) error: {url} / {e}", file=sys.stderr) |
||||
return False |
||||
|
||||
print(f"Attempt to fixing '{files}' is done.") |
||||
return True |
||||
|
||||
|
||||
def pip_install(packages): |
||||
install_cmd = ['#FORCE', sys.executable, "-m", "pip", "install", '-U'] + packages |
||||
try_install_script('pip install via manager', '..', install_cmd) |
||||
|
||||
|
||||
def rmtree(path): |
||||
retry_count = 3 |
||||
|
||||
while True: |
||||
try: |
||||
retry_count -= 1 |
||||
|
||||
if platform.system() == "Windows": |
||||
manager_funcs.run_script(['attrib', '-R', path + '\\*', '/S']) |
||||
shutil.rmtree(path) |
||||
|
||||
return True |
||||
|
||||
except Exception as ex: |
||||
print(f"ex: {ex}") |
||||
time.sleep(3) |
||||
|
||||
if retry_count < 0: |
||||
raise ex |
||||
|
||||
print(f"Uninstall retry({retry_count})") |
||||
|
||||
|
||||
def gitclone_uninstall(files): |
||||
import os |
||||
|
||||
print(f"uninstall: {files}") |
||||
for url in files: |
||||
if url.endswith("/"): |
||||
url = url[:-1] |
||||
try: |
||||
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") |
||||
dir_path = os.path.join(custom_nodes_path, dir_name) |
||||
|
||||
# safety check |
||||
if dir_path == '/' or dir_path[1:] == ":/" or dir_path == '': |
||||
print(f"Uninstall(git-clone) error: invalid path '{dir_path}' for '{url}'") |
||||
return False |
||||
|
||||
install_script_path = os.path.join(dir_path, "uninstall.py") |
||||
disable_script_path = os.path.join(dir_path, "disable.py") |
||||
if os.path.exists(install_script_path): |
||||
uninstall_cmd = [sys.executable, "uninstall.py"] |
||||
code = manager_funcs.run_script(uninstall_cmd, cwd=dir_path) |
||||
|
||||
if code != 0: |
||||
print(f"An error occurred during the execution of the uninstall.py script. Only the '{dir_path}' will be deleted.") |
||||
elif os.path.exists(disable_script_path): |
||||
disable_script = [sys.executable, "disable.py"] |
||||
code = manager_funcs.run_script(disable_script, cwd=dir_path) |
||||
if code != 0: |
||||
print(f"An error occurred during the execution of the disable.py script. Only the '{dir_path}' will be deleted.") |
||||
|
||||
if os.path.exists(dir_path): |
||||
rmtree(dir_path) |
||||
elif os.path.exists(dir_path + ".disabled"): |
||||
rmtree(dir_path + ".disabled") |
||||
except Exception as e: |
||||
print(f"Uninstall(git-clone) error: {url} / {e}", file=sys.stderr) |
||||
return False |
||||
|
||||
print("Uninstallation was successful.") |
||||
return True |
||||
|
||||
|
||||
def gitclone_set_active(files, is_disable): |
||||
import os |
||||
|
||||
if is_disable: |
||||
action_name = "Disable" |
||||
else: |
||||
action_name = "Enable" |
||||
|
||||
print(f"{action_name}: {files}") |
||||
for url in files: |
||||
if url.endswith("/"): |
||||
url = url[:-1] |
||||
try: |
||||
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") |
||||
dir_path = os.path.join(custom_nodes_path, dir_name) |
||||
|
||||
# safey check |
||||
if dir_path == '/' or dir_path[1:] == ":/" or dir_path == '': |
||||
print(f"{action_name}(git-clone) error: invalid path '{dir_path}' for '{url}'") |
||||
return False |
||||
|
||||
if is_disable: |
||||
current_path = dir_path |
||||
new_path = dir_path + ".disabled" |
||||
else: |
||||
current_path = dir_path + ".disabled" |
||||
new_path = dir_path |
||||
|
||||
os.rename(current_path, new_path) |
||||
|
||||
if is_disable: |
||||
if os.path.exists(os.path.join(new_path, "disable.py")): |
||||
disable_script = [sys.executable, "disable.py"] |
||||
try_install_script(url, new_path, disable_script) |
||||
else: |
||||
if os.path.exists(os.path.join(new_path, "enable.py")): |
||||
enable_script = [sys.executable, "enable.py"] |
||||
try_install_script(url, new_path, enable_script) |
||||
|
||||
except Exception as e: |
||||
print(f"{action_name}(git-clone) error: {url} / {e}", file=sys.stderr) |
||||
return False |
||||
|
||||
print(f"{action_name} was successful.") |
||||
return True |
||||
|
||||
|
||||
def gitclone_update(files): |
||||
import os |
||||
|
||||
print(f"Update: {files}") |
||||
for url in files: |
||||
if url.endswith("/"): |
||||
url = url[:-1] |
||||
try: |
||||
repo_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") |
||||
repo_path = os.path.join(custom_nodes_path, repo_name) |
||||
git_pull(repo_path) |
||||
|
||||
if not execute_install_script(url, repo_path, lazy_mode=True): |
||||
return False |
||||
|
||||
except Exception as e: |
||||
print(f"Update(git-clone) error: {url} / {e}", file=sys.stderr) |
||||
return False |
||||
|
||||
print("Update was successful.") |
||||
return True |
||||
|
||||
|
||||
def lookup_customnode_by_url(data, target): |
||||
for x in data['custom_nodes']: |
||||
if target in x['files']: |
||||
dir_name = os.path.splitext(os.path.basename(target))[0].replace(".git", "") |
||||
dir_path = os.path.join(custom_nodes_path, dir_name) |
||||
if os.path.exists(dir_path): |
||||
x['installed'] = 'True' |
||||
elif os.path.exists(dir_path + ".disabled"): |
||||
x['installed'] = 'Disabled' |
||||
return x |
||||
|
||||
return None |
||||
|
||||
|
||||
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: |
||||
url = item['files'][0] |
||||
|
||||
if url.endswith("/"): |
||||
url = url[:-1] |
||||
|
||||
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "") |
||||
dir_path = os.path.join(custom_nodes_path, dir_name) |
||||
if os.path.exists(dir_path): |
||||
try: |
||||
item['installed'] = 'True' # default |
||||
|
||||
if cm_global.try_call(api="cm.is_import_failed_extension", name=dir_name): |
||||
item['installed'] = 'Fail' |
||||
|
||||
if do_update_check: |
||||
update_state, success = git_repo_has_updates(dir_path, do_fetch, do_update) |
||||
if (do_update_check or do_update) and update_state: |
||||
item['installed'] = 'Update' |
||||
elif do_update and not success: |
||||
item['installed'] = 'Fail' |
||||
except: |
||||
if cm_global.try_call(api="cm.is_import_failed_extension", name=dir_name): |
||||
item['installed'] = 'Fail' |
||||
else: |
||||
item['installed'] = 'True' |
||||
|
||||
elif os.path.exists(dir_path + ".disabled"): |
||||
item['installed'] = 'Disabled' |
||||
|
||||
else: |
||||
item['installed'] = 'False' |
||||
|
||||
elif item['install_type'] == 'copy' and len(item['files']) == 1: |
||||
dir_name = os.path.basename(item['files'][0]) |
||||
|
||||
if item['files'][0].endswith('.py'): |
||||
base_path = custom_nodes_path |
||||
elif 'js_path' in item: |
||||
base_path = os.path.join(js_path, item['js_path']) |
||||
else: |
||||
base_path = js_path |
||||
|
||||
file_path = os.path.join(base_path, dir_name) |
||||
if os.path.exists(file_path): |
||||
if cm_global.try_call(api="cm.is_import_failed_extension", name=dir_name): |
||||
item['installed'] = 'Fail' |
||||
else: |
||||
item['installed'] = 'True' |
||||
elif os.path.exists(file_path + ".disabled"): |
||||
item['installed'] = 'Disabled' |
||||
else: |
||||
item['installed'] = 'False' |
Loading…
Reference in new issue