mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-07-07 07:01:46 +08:00
Merge b1fa964486 into b08debceca
This commit is contained in:
commit
1ad787345b
@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import logging
|
import logging
|
||||||
@ -7,6 +8,34 @@ from collections.abc import Collection
|
|||||||
|
|
||||||
from comfy.cli_args import args
|
from comfy.cli_args import args
|
||||||
|
|
||||||
|
# exFAT does not update directory mtime when files are added/removed,
|
||||||
|
# so the cache invalidation needs an extra check on such filesystems.
|
||||||
|
_exfat_checked = False
|
||||||
|
_is_exfat_cache: dict[str, bool] = {}
|
||||||
|
|
||||||
|
def _is_exfat(path: str) -> bool:
|
||||||
|
"""Check if the given path resides on an exFAT volume (Windows only)."""
|
||||||
|
global _exfat_checked, _is_exfat_cache
|
||||||
|
if sys.platform != "win32":
|
||||||
|
return False
|
||||||
|
# Cache per drive letter
|
||||||
|
drive = os.path.splitdrive(path)[0]
|
||||||
|
if drive in _is_exfat_cache:
|
||||||
|
return _is_exfat_cache[drive]
|
||||||
|
try:
|
||||||
|
import ctypes
|
||||||
|
kernel32 = ctypes.windll.kernel32
|
||||||
|
# Get volume information
|
||||||
|
fs_name = ctypes.create_unicode_buffer(256)
|
||||||
|
if kernel32.GetVolumeInformationW(drive + "\\", None, 0, None, None, None, fs_name, 256):
|
||||||
|
result = fs_name.value.upper() == "EXFAT"
|
||||||
|
else:
|
||||||
|
result = False
|
||||||
|
except Exception:
|
||||||
|
result = False
|
||||||
|
_is_exfat_cache[drive] = result
|
||||||
|
return result
|
||||||
|
|
||||||
supported_pt_extensions: set[str] = {'.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft'}
|
supported_pt_extensions: set[str] = {'.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft'}
|
||||||
|
|
||||||
folder_names_and_paths: dict[str, tuple[list[str], set[str]]] = {}
|
folder_names_and_paths: dict[str, tuple[list[str], set[str]]] = {}
|
||||||
@ -369,19 +398,22 @@ def get_folder_paths(folder_name: str) -> list[str]:
|
|||||||
folder_name = map_legacy(folder_name)
|
folder_name = map_legacy(folder_name)
|
||||||
return folder_names_and_paths[folder_name][0][:]
|
return folder_names_and_paths[folder_name][0][:]
|
||||||
|
|
||||||
def recursive_search(directory: str, excluded_dir_names: list[str] | None=None) -> tuple[list[str], dict[str, float]]:
|
def recursive_search(directory: str, excluded_dir_names: list[str] | None=None) -> tuple[list[str], dict[str, float], dict[str, int]]:
|
||||||
if not os.path.isdir(directory):
|
if not os.path.isdir(directory):
|
||||||
return [], {}
|
return [], {}, {}
|
||||||
|
|
||||||
if excluded_dir_names is None:
|
if excluded_dir_names is None:
|
||||||
excluded_dir_names = []
|
excluded_dir_names = []
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
dirs = {}
|
dirs = {}
|
||||||
|
entry_counts = {}
|
||||||
|
|
||||||
# Attempt to add the initial directory to dirs with error handling
|
# Attempt to add the initial directory to dirs with error handling
|
||||||
try:
|
try:
|
||||||
dirs[directory] = os.path.getmtime(directory)
|
dirs[directory] = os.path.getmtime(directory)
|
||||||
|
if _is_exfat(directory):
|
||||||
|
entry_counts[directory] = len(os.listdir(directory))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
logging.warning(f"Warning: Unable to access {directory}. Skipping this path.")
|
logging.warning(f"Warning: Unable to access {directory}. Skipping this path.")
|
||||||
|
|
||||||
@ -404,11 +436,13 @@ def recursive_search(directory: str, excluded_dir_names: list[str] | None=None)
|
|||||||
path: str = os.path.join(dirpath, d)
|
path: str = os.path.join(dirpath, d)
|
||||||
try:
|
try:
|
||||||
dirs[path] = os.path.getmtime(path)
|
dirs[path] = os.path.getmtime(path)
|
||||||
|
if _is_exfat(path):
|
||||||
|
entry_counts[path] = len(os.listdir(path))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
logging.warning(f"Warning: Unable to access {path}. Skipping this path.")
|
logging.warning(f"Warning: Unable to access {path}. Skipping this path.")
|
||||||
continue
|
continue
|
||||||
logging.debug("found {} files".format(len(result)))
|
logging.debug("found {} files".format(len(result)))
|
||||||
return result, dirs
|
return result, dirs, entry_counts
|
||||||
|
|
||||||
def filter_files_extensions(files: Collection[str], extensions: Collection[str]) -> list[str]:
|
def filter_files_extensions(files: Collection[str], extensions: Collection[str]) -> list[str]:
|
||||||
return sorted(list(filter(lambda a: os.path.splitext(a)[-1].lower() in extensions or len(extensions) == 0, files)))
|
return sorted(list(filter(lambda a: os.path.splitext(a)[-1].lower() in extensions or len(extensions) == 0, files)))
|
||||||
@ -451,11 +485,16 @@ def get_filename_list_(folder_name: str) -> tuple[list[str], dict[str, float], f
|
|||||||
output_list = set()
|
output_list = set()
|
||||||
folders = folder_names_and_paths[folder_name]
|
folders = folder_names_and_paths[folder_name]
|
||||||
output_folders = {}
|
output_folders = {}
|
||||||
|
all_entry_counts = {}
|
||||||
for x in folders[0]:
|
for x in folders[0]:
|
||||||
files, folders_all = recursive_search(x, excluded_dir_names=[".git"])
|
files, folders_all, entry_counts = recursive_search(x, excluded_dir_names=[".git"])
|
||||||
output_list.update(filter_files_extensions(files, folders[1]))
|
output_list.update(filter_files_extensions(files, folders[1]))
|
||||||
output_folders = {**output_folders, **folders_all}
|
output_folders = {**output_folders, **folders_all}
|
||||||
|
# Store entry counts with a key suffix to avoid colliding with mtime keys
|
||||||
|
for k, v in entry_counts.items():
|
||||||
|
all_entry_counts[k + "::entry_count"] = v
|
||||||
|
|
||||||
|
output_folders.update(all_entry_counts)
|
||||||
return sorted(list(output_list)), output_folders, time.perf_counter()
|
return sorted(list(output_list)), output_folders, time.perf_counter()
|
||||||
|
|
||||||
def cached_filename_list_(folder_name: str) -> tuple[list[str], dict[str, float], float] | None:
|
def cached_filename_list_(folder_name: str) -> tuple[list[str], dict[str, float], float] | None:
|
||||||
@ -471,10 +510,25 @@ def cached_filename_list_(folder_name: str) -> tuple[list[str], dict[str, float]
|
|||||||
out = filename_list_cache[folder_name]
|
out = filename_list_cache[folder_name]
|
||||||
|
|
||||||
for x in out[1]:
|
for x in out[1]:
|
||||||
|
# Skip entry count keys used for exFAT cache invalidation
|
||||||
|
if x.endswith("::entry_count"):
|
||||||
|
continue
|
||||||
time_modified = out[1][x]
|
time_modified = out[1][x]
|
||||||
folder = x
|
folder = x
|
||||||
if os.path.getmtime(folder) != time_modified:
|
try:
|
||||||
|
current_mtime = os.path.getmtime(folder)
|
||||||
|
except FileNotFoundError:
|
||||||
return None
|
return None
|
||||||
|
if current_mtime != time_modified:
|
||||||
|
return None
|
||||||
|
# exFAT does not update directory mtime on file changes;
|
||||||
|
# use entry count as a fallback invalidation signal.
|
||||||
|
if _is_exfat(folder):
|
||||||
|
try:
|
||||||
|
if len(os.listdir(folder)) != out[1][folder + "::entry_count"]:
|
||||||
|
return None
|
||||||
|
except (KeyError, FileNotFoundError):
|
||||||
|
return None
|
||||||
|
|
||||||
folders = folder_names_and_paths[folder_name]
|
folders = folder_names_and_paths[folder_name]
|
||||||
for x in folders[0]:
|
for x in folders[0]:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user