Skip to content

Commit c6edf60

Browse files
committed
fix quick update button and some bugs
1 parent 6e492a7 commit c6edf60

1 file changed

Lines changed: 48 additions & 11 deletions

File tree

BlenderUpdater.py

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
CONFIG_SECTION_MAIN = "main"
5353
CONFIG_KEY_PATH = "path"
5454
CONFIG_KEY_LAST_CHECK = "lastcheck"
55-
CONFIG_KEY_LAST_DL_DESC = "lastdl_desc"
5655
CONFIG_KEY_LAST_DL_FILENAME = "lastdl_filename"
5756
CONFIG_KEY_INSTALLED_FILENAME = "installed_filename"
5857
CONFIG_KEY_OS_FILTER = "os_filter"
@@ -92,6 +91,24 @@
9291
logger = logging.getLogger()
9392

9493

94+
_BUILD_LABEL_RE = re.compile(
95+
r"blender-(\d+\.\d+[^-]*)-(?:.*-)?(windows|linux|darwin|macos)[\.\-]?(\w+)?",
96+
re.IGNORECASE,
97+
)
98+
99+
100+
def _build_label(filename: str) -> str:
101+
"""Return a short human-readable label for a Blender build filename."""
102+
m = _BUILD_LABEL_RE.search(filename)
103+
if m:
104+
version, os_name, arch = m.group(1), m.group(2), m.group(3)
105+
os_label = OS_DESCRIPTIONS.get(os_name.lower(), os_name)
106+
return f"Blender {version} ({os_label}{' ' + arch if arch else ''})"
107+
# Fallback: strip prefix and extension
108+
stem = re.sub(r"\.(zip|tar\.xz|dmg|tar\.gz)$", "", filename, flags=re.IGNORECASE)
109+
return stem.removeprefix("blender-")
110+
111+
95112
def _hbytes(num: float) -> str:
96113
if not isinstance(num, (int, float)):
97114
return "0 bytes"
@@ -257,6 +274,7 @@ def run(self):
257274
downloaded_size = 0
258275
for chunk in response.iter_content(chunk_size=DOWNLOAD_CHUNK_SIZE):
259276
if self._cancelled:
277+
response.close()
260278
self.signals.finished.emit(False, CANCEL_MESSAGE)
261279
return
262280
f.write(chunk)
@@ -291,8 +309,16 @@ def run(self):
291309
extract_dir = os.path.join(self.temp_dir, "extracted")
292310
os.makedirs(extract_dir, exist_ok=True)
293311
shutil.unpack_archive(self.download_path, extract_dir)
294-
source_dir_name = next(os.walk(extract_dir))[1][0]
295-
source_path = os.path.join(extract_dir, source_dir_name)
312+
313+
# Zip-slip guard: ensure no extracted path escapes the extract directory
314+
extract_dir_resolved = Path(extract_dir).resolve()
315+
for member in extract_dir_resolved.rglob("*"):
316+
member.resolve().relative_to(extract_dir_resolved)
317+
318+
_, subdirs, _ = next(os.walk(extract_dir))
319+
if not subdirs:
320+
raise OSError("Archive did not contain a top-level directory as expected")
321+
source_path = os.path.join(extract_dir, subdirs[0])
296322

297323
# Copying
298324
self.signals.copying_started.emit()
@@ -327,6 +353,7 @@ def __init__(self, parent=None):
327353
r'blender-\d+\.\d+[^"\s/]*\.(?:zip|tar\.xz|dmg|tar\.gz)'
328354
)
329355
self.threadpool = QThreadPool()
356+
self.finallist = []
330357
logger.info(
331358
f"Multithreading with maximum {self.threadpool.maxThreadCount()} threads"
332359
)
@@ -372,10 +399,11 @@ def __init__(self, parent=None):
372399
self.line_path.setText(self.install_path)
373400

374401
last_dl_filename = self._get_config(CONFIG_KEY_LAST_DL_FILENAME)
375-
last_dl_desc = self._get_config(CONFIG_KEY_LAST_DL_DESC)
376-
if last_dl_filename and last_dl_desc:
377-
self.btn_oneclick.setText(f"{last_dl_filename} | {last_dl_desc}")
402+
if last_dl_filename:
403+
self.btn_oneclick.setText(_build_label(last_dl_filename))
404+
self.btn_oneclick.clicked.connect(lambda: self.download(last_dl_filename))
378405
self.btn_oneclick.show()
406+
self.lbl_quick.show()
379407

380408
self.btn_cancel.hide()
381409
self.frm_progress.hide()
@@ -408,7 +436,7 @@ def __init__(self, parent=None):
408436
logger.critical("No internet connection")
409437

410438
try:
411-
response = self.session.get(GITHUB_RELEASES_API_URL)
439+
response = self.session.get(GITHUB_RELEASES_API_URL, timeout=CONNECTIVITY_TIMEOUT)
412440
response.raise_for_status()
413441
update_data = response.json()
414442
logger.info("Reading existing configuration file")
@@ -479,7 +507,6 @@ def _load_config(self):
479507
defaults = {
480508
CONFIG_KEY_PATH: "",
481509
CONFIG_KEY_LAST_CHECK: "Never",
482-
CONFIG_KEY_LAST_DL_DESC: "",
483510
CONFIG_KEY_LAST_DL_FILENAME: "",
484511
CONFIG_KEY_INSTALLED_FILENAME: "",
485512
CONFIG_KEY_OS_FILTER: "all",
@@ -587,6 +614,12 @@ def on_check_finished(self, build_list, error):
587614

588615
self.finallist = build_list
589616

617+
last_dl_filename = self._get_config(CONFIG_KEY_LAST_DL_FILENAME)
618+
if last_dl_filename and last_dl_filename not in build_list:
619+
self._update_config(CONFIG_KEY_LAST_DL_FILENAME, "")
620+
self.btn_oneclick.hide()
621+
self.lbl_quick.hide()
622+
590623
self.appleicon = QtGui.QIcon(":/newPrefix/images/Apple-icon.png")
591624
self.windowsicon = QtGui.QIcon(":/newPrefix/images/Windows-icon.png")
592625
self.linuxicon = QtGui.QIcon(":/newPrefix/images/Linux-icon.png")
@@ -766,9 +799,13 @@ def done(self, installed_entry_filename):
766799
elif opsys == "Linux":
767800
self.btn_execute.clicked.connect(self.exec_linux)
768801

769-
last_dl_desc = self._get_config(CONFIG_KEY_LAST_DL_DESC)
770-
if last_dl_desc and installed_entry_filename:
771-
self.btn_oneclick.setText(f"{installed_entry_filename} | {last_dl_desc}")
802+
if installed_entry_filename:
803+
self.btn_oneclick.setText(_build_label(installed_entry_filename))
804+
try:
805+
self.btn_oneclick.clicked.disconnect()
806+
except RuntimeError:
807+
pass
808+
self.btn_oneclick.clicked.connect(lambda: self.download(installed_entry_filename))
772809
self.btn_oneclick.show()
773810
self.lbl_quick.show()
774811
else:

0 commit comments

Comments
 (0)