Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
automatic1111
GitHub Repository: automatic1111/stable-diffusion-webui
Path: blob/master/modules/config_states.py
3055 views
1
"""
2
Supports saving and restoring webui and extensions from a known working set of commits
3
"""
4
5
import os
6
import json
7
import tqdm
8
9
from datetime import datetime
10
import git
11
12
from modules import shared, extensions, errors
13
from modules.paths_internal import script_path, config_states_dir
14
15
all_config_states = {}
16
17
18
def list_config_states():
19
global all_config_states
20
21
all_config_states.clear()
22
os.makedirs(config_states_dir, exist_ok=True)
23
24
config_states = []
25
for filename in os.listdir(config_states_dir):
26
if filename.endswith(".json"):
27
path = os.path.join(config_states_dir, filename)
28
try:
29
with open(path, "r", encoding="utf-8") as f:
30
j = json.load(f)
31
assert "created_at" in j, '"created_at" does not exist'
32
j["filepath"] = path
33
config_states.append(j)
34
except Exception as e:
35
print(f'[ERROR]: Config states {path}, {e}')
36
37
config_states = sorted(config_states, key=lambda cs: cs["created_at"], reverse=True)
38
39
for cs in config_states:
40
timestamp = datetime.fromtimestamp(cs["created_at"]).strftime('%Y-%m-%d %H:%M:%S')
41
name = cs.get("name", "Config")
42
full_name = f"{name}: {timestamp}"
43
all_config_states[full_name] = cs
44
45
return all_config_states
46
47
48
def get_webui_config():
49
webui_repo = None
50
51
try:
52
if os.path.exists(os.path.join(script_path, ".git")):
53
webui_repo = git.Repo(script_path)
54
except Exception:
55
errors.report(f"Error reading webui git info from {script_path}", exc_info=True)
56
57
webui_remote = None
58
webui_commit_hash = None
59
webui_commit_date = None
60
webui_branch = None
61
if webui_repo and not webui_repo.bare:
62
try:
63
webui_remote = next(webui_repo.remote().urls, None)
64
head = webui_repo.head.commit
65
webui_commit_date = webui_repo.head.commit.committed_date
66
webui_commit_hash = head.hexsha
67
webui_branch = webui_repo.active_branch.name
68
69
except Exception:
70
webui_remote = None
71
72
return {
73
"remote": webui_remote,
74
"commit_hash": webui_commit_hash,
75
"commit_date": webui_commit_date,
76
"branch": webui_branch,
77
}
78
79
80
def get_extension_config():
81
ext_config = {}
82
83
for ext in extensions.extensions:
84
ext.read_info_from_repo()
85
86
entry = {
87
"name": ext.name,
88
"path": ext.path,
89
"enabled": ext.enabled,
90
"is_builtin": ext.is_builtin,
91
"remote": ext.remote,
92
"commit_hash": ext.commit_hash,
93
"commit_date": ext.commit_date,
94
"branch": ext.branch,
95
"have_info_from_repo": ext.have_info_from_repo
96
}
97
98
ext_config[ext.name] = entry
99
100
return ext_config
101
102
103
def get_config():
104
creation_time = datetime.now().timestamp()
105
webui_config = get_webui_config()
106
ext_config = get_extension_config()
107
108
return {
109
"created_at": creation_time,
110
"webui": webui_config,
111
"extensions": ext_config
112
}
113
114
115
def restore_webui_config(config):
116
print("* Restoring webui state...")
117
118
if "webui" not in config:
119
print("Error: No webui data saved to config")
120
return
121
122
webui_config = config["webui"]
123
124
if "commit_hash" not in webui_config:
125
print("Error: No commit saved to webui config")
126
return
127
128
webui_commit_hash = webui_config.get("commit_hash", None)
129
webui_repo = None
130
131
try:
132
if os.path.exists(os.path.join(script_path, ".git")):
133
webui_repo = git.Repo(script_path)
134
except Exception:
135
errors.report(f"Error reading webui git info from {script_path}", exc_info=True)
136
return
137
138
try:
139
webui_repo.git.fetch(all=True)
140
webui_repo.git.reset(webui_commit_hash, hard=True)
141
print(f"* Restored webui to commit {webui_commit_hash}.")
142
except Exception:
143
errors.report(f"Error restoring webui to commit{webui_commit_hash}")
144
145
146
def restore_extension_config(config):
147
print("* Restoring extension state...")
148
149
if "extensions" not in config:
150
print("Error: No extension data saved to config")
151
return
152
153
ext_config = config["extensions"]
154
155
results = []
156
disabled = []
157
158
for ext in tqdm.tqdm(extensions.extensions):
159
if ext.is_builtin:
160
continue
161
162
ext.read_info_from_repo()
163
current_commit = ext.commit_hash
164
165
if ext.name not in ext_config:
166
ext.disabled = True
167
disabled.append(ext.name)
168
results.append((ext, current_commit[:8], False, "Saved extension state not found in config, marking as disabled"))
169
continue
170
171
entry = ext_config[ext.name]
172
173
if "commit_hash" in entry and entry["commit_hash"]:
174
try:
175
ext.fetch_and_reset_hard(entry["commit_hash"])
176
ext.read_info_from_repo()
177
if current_commit != entry["commit_hash"]:
178
results.append((ext, current_commit[:8], True, entry["commit_hash"][:8]))
179
except Exception as ex:
180
results.append((ext, current_commit[:8], False, ex))
181
else:
182
results.append((ext, current_commit[:8], False, "No commit hash found in config"))
183
184
if not entry.get("enabled", False):
185
ext.disabled = True
186
disabled.append(ext.name)
187
else:
188
ext.disabled = False
189
190
shared.opts.disabled_extensions = disabled
191
shared.opts.save(shared.config_filename)
192
193
print("* Finished restoring extensions. Results:")
194
for ext, prev_commit, success, result in results:
195
if success:
196
print(f" + {ext.name}: {prev_commit} -> {result}")
197
else:
198
print(f" ! {ext.name}: FAILURE ({result})")
199
200