提交 f3320b80 编写于 作者: S space-nuko

Various UI fixes in config state tab

上级 f22d0dde
...@@ -33,3 +33,4 @@ notification.mp3 ...@@ -33,3 +33,4 @@ notification.mp3
/test/stdout.txt /test/stdout.txt
/test/stderr.txt /test/stderr.txt
/cache.json /cache.json
/config_states/
...@@ -50,7 +50,7 @@ function install_extension_from_index(button, url){ ...@@ -50,7 +50,7 @@ function install_extension_from_index(button, url){
function config_state_confirm_restore(_, config_state_name, config_restore_type) { function config_state_confirm_restore(_, config_state_name, config_restore_type) {
if (config_state_name == "Current") { if (config_state_name == "Current") {
return [false, config_state_name]; return [false, config_state_name, config_restore_type];
} }
let restored = ""; let restored = "";
if (config_restore_type == "extensions") { if (config_restore_type == "extensions") {
...@@ -60,6 +60,12 @@ function config_state_confirm_restore(_, config_state_name, config_restore_type) ...@@ -60,6 +60,12 @@ function config_state_confirm_restore(_, config_state_name, config_restore_type)
} else { } else {
restored = "the webui version and all saved extension versions"; restored = "the webui version and all saved extension versions";
} }
let confirmed = confirm("Are you sure you want to restore from this state?\nThis will reset " + restored + ".\n(A backup of the current state will be made.)"); let confirmed = confirm("Are you sure you want to restore from this state?\nThis will reset " + restored + ".");
if (confirmed) {
restart_reload();
gradioApp().querySelectorAll('#extensions .extension_status').forEach(function(x){
x.innerHTML = "Loading..."
})
}
return [confirmed, config_state_name, config_restore_type]; return [confirmed, config_state_name, config_restore_type];
} }
"""
Supports saving and restoring webui and extensions from a known working set of commits
"""
import os
import sys
import traceback
import json
import time
import tqdm
from datetime import datetime
from collections import OrderedDict
import git
from modules import shared, extensions
from modules.paths_internal import extensions_dir, extensions_builtin_dir, script_path, config_states_dir
all_config_states = OrderedDict()
def list_config_states():
global all_config_states
all_config_states.clear()
os.makedirs(config_states_dir, exist_ok=True)
config_states = []
for filename in os.listdir(config_states_dir):
if filename.endswith(".json"):
path = os.path.join(config_states_dir, filename)
with open(path, "r", encoding="utf-8") as f:
j = json.load(f)
j["filepath"] = path
config_states.append(j)
config_states = list(sorted(config_states, key=lambda cs: cs["created_at"], reverse=True))
for cs in config_states:
timestamp = time.asctime(time.gmtime(cs["created_at"]))
name = cs.get("name", "Config")
full_name = f"{name}: {timestamp}"
all_config_states[full_name] = cs
return all_config_states
def get_webui_config():
webui_repo = None
try:
if os.path.exists(os.path.join(script_path, ".git")):
webui_repo = git.Repo(script_path)
except Exception:
print(f"Error reading webui git info from {script_path}:", file=sys.stderr)
print(traceback.format_exc(), file=sys.stderr)
webui_remote = None
webui_commit_hash = None
webui_commit_date = None
webui_branch = None
if webui_repo and not webui_repo.bare:
try:
webui_remote = next(webui_repo.remote().urls, None)
head = webui_repo.head.commit
webui_commit_date = webui_repo.head.commit.committed_date
webui_commit_hash = head.hexsha
webui_branch = webui_repo.active_branch.name
except Exception:
webui_remote = None
return {
"remote": webui_remote,
"commit_hash": webui_commit_hash,
"commit_date": webui_commit_date,
"branch": webui_branch,
}
def get_extension_config():
ext_config = {}
for ext in extensions.extensions:
entry = {
"name": ext.name,
"path": ext.path,
"enabled": ext.enabled,
"is_builtin": ext.is_builtin,
"remote": ext.remote,
"commit_hash": ext.commit_hash,
"commit_date": ext.commit_date,
"branch": ext.branch,
"have_info_from_repo": ext.have_info_from_repo
}
ext_config[ext.name] = entry
return ext_config
def get_config():
creation_time = datetime.now().timestamp()
webui_config = get_webui_config()
ext_config = get_extension_config()
return {
"created_at": creation_time,
"webui": webui_config,
"extensions": ext_config
}
def restore_webui_config(config):
print("* Restoring webui state...")
if "webui" not in config:
print("Error: No webui data saved to config")
return
webui_config = config["webui"]
if "commit_hash" not in webui_config:
print("Error: No commit saved to webui config")
return
webui_commit_hash = webui_config.get("commit_hash", None)
webui_repo = None
try:
if os.path.exists(os.path.join(script_path, ".git")):
webui_repo = git.Repo(script_path)
except Exception:
print(f"Error reading webui git info from {script_path}:", file=sys.stderr)
print(traceback.format_exc(), file=sys.stderr)
return
try:
webui_repo.git.fetch(all=True)
webui_repo.git.reset(webui_commit_hash, hard=True)
print(f"* Restored webui to commit {webui_commit_hash}.")
except Exception:
print(f"Error restoring webui to commit {webui_commit_hash}:", file=sys.stderr)
print(traceback.format_exc(), file=sys.stderr)
def restore_extension_config(config):
print("* Restoring extension state...")
if "extensions" not in config:
print("Error: No extension data saved to config")
return
ext_config = config["extensions"]
results = []
disabled = []
for ext in tqdm.tqdm(extensions.extensions):
if ext.is_builtin:
continue
ext.read_info_from_repo()
current_commit = ext.commit_hash
if ext.name not in ext_config:
ext.disabled = True
disabled.append(ext.name)
results.append((ext, current_commit[:8], False, "Saved extension state not found in config, marking as disabled"))
continue
entry = ext_config[ext.name]
if "commit_hash" in entry and entry["commit_hash"]:
try:
ext.fetch_and_reset_hard(entry["commit_hash"])
ext.read_info_from_repo()
if current_commit != entry["commit_hash"]:
results.append((ext, current_commit[:8], True, entry["commit_hash"][:8]))
except Exception as ex:
results.append((ext, current_commit[:8], False, ex))
else:
results.append((ext, current_commit[:8], False, "No commit hash found in config"))
if not entry.get("enabled", False):
ext.disabled = True
disabled.append(ext.name)
else:
ext.disabled = False
shared.opts.disabled_extensions = disabled
shared.opts.save(shared.config_filename)
print("* Finished restoring extensions. Results:")
for ext, prev_commit, success, result in results:
if success:
print(f" + {ext.name}: {prev_commit} -> {result}")
else:
print(f" ! {ext.name}: FAILURE ({result})")
...@@ -17,6 +17,7 @@ from modules.paths_internal import config_states_dir ...@@ -17,6 +17,7 @@ from modules.paths_internal import config_states_dir
from modules.call_queue import wrap_gradio_gpu_call from modules.call_queue import wrap_gradio_gpu_call
available_extensions = {"extensions": []} available_extensions = {"extensions": []}
STYLE_PRIMARY = ' style="color: var(--primary-400)"'
def check_access(): def check_access():
...@@ -67,7 +68,7 @@ def save_config_state(name): ...@@ -67,7 +68,7 @@ def save_config_state(name):
config_states.list_config_states() config_states.list_config_states()
new_value = next(iter(config_states.all_config_states.keys()), "Current") new_value = next(iter(config_states.all_config_states.keys()), "Current")
new_choices = ["Current"] + list(config_states.all_config_states.keys()) new_choices = ["Current"] + list(config_states.all_config_states.keys())
return gr.Dropdown.update(value=new_value, choices=new_choices), f"<span>Saved current webui/extension state to '{filename}'</span>" return gr.Dropdown.update(value=new_value, choices=new_choices), f"<span>Saved current webui/extension state to \"{filename}\"</span>"
def restore_config_state(confirmed, config_state_name, restore_type): def restore_config_state(confirmed, config_state_name, restore_type):
...@@ -78,14 +79,12 @@ def restore_config_state(confirmed, config_state_name, restore_type): ...@@ -78,14 +79,12 @@ def restore_config_state(confirmed, config_state_name, restore_type):
check_access() check_access()
save_config_state("Backup (pre-restore)")
config_state = config_states.all_config_states[config_state_name] config_state = config_states.all_config_states[config_state_name]
print(f"Restoring webui state from backup: {restore_type}") print(f"*** Restoring webui state from backup: {restore_type} ***")
if restore_type == "extensions" or restore_type == "both": if restore_type == "extensions" or restore_type == "both":
shared.opts.restore_config_state_file = config_state["filename"] shared.opts.restore_config_state_file = config_state["filepath"]
shared.opts.save(shared.config_filename) shared.opts.save(shared.config_filename)
if restore_type == "webui" or restore_type == "both": if restore_type == "webui" or restore_type == "both":
...@@ -149,7 +148,7 @@ def extension_table(): ...@@ -149,7 +148,7 @@ def extension_table():
style = "" style = ""
if shared.opts.disable_all_extensions == "extra" and not ext.is_builtin or shared.opts.disable_all_extensions == "all": if shared.opts.disable_all_extensions == "extra" and not ext.is_builtin or shared.opts.disable_all_extensions == "all":
style = ' style="color: var(--primary-400)"' style = STYLE_PRIMARY
code += f""" code += f"""
<tr> <tr>
...@@ -181,17 +180,25 @@ def update_config_states_table(state_name): ...@@ -181,17 +180,25 @@ def update_config_states_table(state_name):
webui_remote = config_state["webui"]["remote"] or "" webui_remote = config_state["webui"]["remote"] or ""
webui_branch = config_state["webui"]["branch"] webui_branch = config_state["webui"]["branch"]
webui_commit_hash = config_state["webui"]["commit_hash"] webui_commit_hash = config_state["webui"]["commit_hash"] or "<unknown>"
if webui_commit_hash:
webui_commit_hash = webui_commit_hash[:8]
else:
webui_commit_hash = "<unknown>"
webui_commit_date = config_state["webui"]["commit_date"] webui_commit_date = config_state["webui"]["commit_date"]
if webui_commit_date: if webui_commit_date:
webui_commit_date = time.asctime(time.gmtime(webui_commit_date)) webui_commit_date = time.asctime(time.gmtime(webui_commit_date))
else: else:
webui_commit_date = "<unknown>" webui_commit_date = "<unknown>"
current_webui = config_states.get_webui_config()
style_remote = ""
style_branch = ""
style_commit = ""
if current_webui["remote"] != webui_remote:
style_remote = STYLE_PRIMARY
if current_webui["branch"] != webui_branch:
style_branch = STYLE_PRIMARY
if current_webui["commit_hash"] != webui_commit_hash:
style_commit = STYLE_PRIMARY
code += f"""<h2>Config Backup: {config_name}</h2> code += f"""<h2>Config Backup: {config_name}</h2>
<span>Created at: {created_date}</span>""" <span>Created at: {created_date}</span>"""
...@@ -207,10 +214,10 @@ def update_config_states_table(state_name): ...@@ -207,10 +214,10 @@ def update_config_states_table(state_name):
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>{webui_remote}</td> <td><label{style_remote}>{webui_remote}</label></td>
<td>{webui_branch}</td> <td><label{style_branch}>{webui_branch}</label></td>
<td>{webui_commit_hash}</td> <td><label{style_commit}>{webui_commit_hash[:8]}</label></td>
<td>{webui_commit_date}</td> <td><label{style_commit}>{webui_commit_date}</label></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
...@@ -253,13 +260,13 @@ def update_config_states_table(state_name): ...@@ -253,13 +260,13 @@ def update_config_states_table(state_name):
current_ext = ext_map[ext_name] current_ext = ext_map[ext_name]
current_ext.read_info_from_repo() current_ext.read_info_from_repo()
if current_ext.enabled != ext_enabled: if current_ext.enabled != ext_enabled:
style_enabled = ' style="color: var(--primary-400)"' style_enabled = STYLE_PRIMARY
if current_ext.remote != ext_remote: if current_ext.remote != ext_remote:
style_remote = ' style="color: var(--primary-400)"' style_remote = STYLE_PRIMARY
if current_ext.branch != ext_branch: if current_ext.branch != ext_branch:
style_branch = ' style="color: var(--primary-400)"' style_branch = STYLE_PRIMARY
if current_ext.commit_hash != ext_commit_hash: if current_ext.commit_hash != ext_commit_hash:
style_commit = ' style="color: var(--primary-400)"' style_commit = STYLE_PRIMARY
code += f""" code += f"""
<tr> <tr>
......
...@@ -114,8 +114,10 @@ def initialize(): ...@@ -114,8 +114,10 @@ def initialize():
print(f"*** About to restore extension state from file: {config_state_file}") print(f"*** About to restore extension state from file: {config_state_file}")
with open(config_state_file, "r", encoding="utf-8") as f: with open(config_state_file, "r", encoding="utf-8") as f:
config_state = json.load(f) config_state = json.load(f)
config_states.restore_extension_state(config_state) config_states.restore_extension_config(config_state)
startup_timer.record("restore extension config") startup_timer.record("restore extension config")
else:
print(f"!!! Config state backup not found: {config_state_file}")
if cmd_opts.ui_debug_mode: if cmd_opts.ui_debug_mode:
shared.sd_upscalers = upscaler.UpscalerLanczos().scalers shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
...@@ -321,8 +323,10 @@ def webui(): ...@@ -321,8 +323,10 @@ def webui():
print(f"*** About to restore extension state from file: {config_state_file}") print(f"*** About to restore extension state from file: {config_state_file}")
with open(config_state_file, "r", encoding="utf-8") as f: with open(config_state_file, "r", encoding="utf-8") as f:
config_state = json.load(f) config_state = json.load(f)
config_states.restore_extension_state(config_state) config_states.restore_extension_config(config_state)
startup_timer.record("restore extension config") startup_timer.record("restore extension config")
else:
print(f"!!! Config state backup not found: {config_state_file}")
localization.list_localizations(cmd_opts.localizations_dir) localization.list_localizations(cmd_opts.localizations_dir)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册