Skip to content

Commit 3ef9fe6

Browse files
authored
Merge-fix: updater
2 parents 5fc1eae + db80701 commit 3ef9fe6

File tree

15 files changed

+865
-29
lines changed

15 files changed

+865
-29
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ src/
189189
!GUI/src/preview_format/
190190
!GUI/src/material_ct.py
191191
!GUI/src/__init__.py
192+
!deploy/installer/src/
192193
temp
193194
*-in.txt
194195
untitled*

GUI/manager/__init__.py

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import os
2-
import json
3-
from pathlib import Path
42
import subprocess
53
import typing as t
64

@@ -12,7 +10,7 @@
1210
from assets import res
1311
from variables import PYPI_SOURCE
1412
from deploy.update import Proj
15-
from utils import conf, ori_path, env, uv_exc, exc_p, TaskObj, TasksObj
13+
from utils import conf, env, uv_exc, exc_p, TaskObj, TasksObj
1614
from utils.processed_class import PreviewHtml
1715
from utils.sql import SqlRecorder
1816
from GUI.uic.qfluent.components import (
@@ -176,24 +174,103 @@ def rerun(self):
176174
QTimer.singleShot(1000, self.gui.close)
177175

178176
def to_update(self, ver):
179-
# self.gui.open_url_by_browser(self.changelog_url)
180-
uv_env = {key: os.environ[key] for key in ('UV_TOOL_DIR', 'UV_TOOL_BIN_DIR') if key in os.environ}
181-
tool_dir = Path(uv_env['UV_TOOL_DIR'])
182-
if os.name == "nt":
183-
python_exc = tool_dir / "comicguispider" / "Scripts" / "python.exe"
184-
else:
185-
python_exc = tool_dir / "comicguispider" / "bin" / "python"
186-
with ori_path.joinpath("assets/update.txt").open("r", encoding="utf-8") as f:
187-
template = f.read()
188-
updater_script = template.replace(r"{uv_env_dict}", json.dumps(uv_env, ensure_ascii=False))
189-
script_path = tool_dir.joinpath("cgs_update.py")
190-
with open(script_path, "w", encoding="utf-8") as f:
191-
f.write(updater_script)
192-
args = [str(python_exc), str(script_path),
193-
'--uv-exc', uv_exc, '--version', ver,
194-
'--index-url', PYPI_SOURCE[conf.pypi_source]]
195-
if os.name == "nt":
196-
subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_CONSOLE, env=env)
197-
else:
198-
subprocess.Popen(args, start_new_session=True, env=env)
177+
_UpdateLauncher(ver).run()
199178
self.gui.close()
179+
180+
181+
class _UpdateLauncher:
182+
def __init__(self, ver: str):
183+
self.ver = ver
184+
self.install_spec = f"ComicGUISpider=={ver}"
185+
self.index_url = PYPI_SOURCE[conf.pypi_source]
186+
self.log_path = exc_p / "cgs_update.log"
187+
self.installer_exe = exc_p / "runtime" / "installer.exe"
188+
189+
def run(self):
190+
if os.name == "nt" and self.installer_exe.exists():
191+
self._run_installer()
192+
return
193+
if os.name == "nt":
194+
self._run_windows_fallback()
195+
return
196+
self._run_posix_fallback()
197+
198+
def _run_installer(self):
199+
args = [
200+
str(self.installer_exe),
201+
"--version", self.ver,
202+
"--uv-exc", uv_exc,
203+
"--index-url", self.index_url,
204+
"--parent-pid", str(os.getpid()),
205+
]
206+
for key in ("UV_TOOL_DIR", "UV_TOOL_BIN_DIR"):
207+
value = os.environ.get(key)
208+
if value:
209+
args.extend([f"--{key.lower().replace('_', '-')}", value])
210+
subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_CONSOLE, env=env)
211+
212+
def _run_windows_fallback(self):
213+
ps1_path = exc_p / "updater.ps1"
214+
script = r"""param(
215+
[Parameter(Mandatory = $true)][string]$UvExe,
216+
[Parameter(Mandatory = $true)][string]$InstallSpec,
217+
[Parameter(Mandatory = $true)][string]$IndexUrl,
218+
[Parameter(Mandatory = $true)][string]$LogPath,
219+
[string]$UvToolDir = "",
220+
[string]$UvToolBinDir = ""
221+
)
222+
223+
if ($UvToolDir) { $env:UV_TOOL_DIR = $UvToolDir }
224+
if ($UvToolBinDir) { $env:UV_TOOL_BIN_DIR = $UvToolBinDir }
225+
226+
& $UvExe tool install $InstallSpec --force --index-url $IndexUrl 2>&1 |
227+
Tee-Object -FilePath $LogPath
228+
229+
if ($LASTEXITCODE -ne 0) {
230+
Write-Host "`nUpdate failed (exit code: $LASTEXITCODE)" -ForegroundColor Red
231+
}
232+
233+
Read-Host "Press Enter to close"
234+
"""
235+
self._write(ps1_path, script)
236+
subprocess.Popen(
237+
[
238+
"powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-NoExit",
239+
"-File", str(ps1_path),
240+
"-UvExe", uv_exc,
241+
"-InstallSpec", self.install_spec,
242+
"-IndexUrl", self.index_url,
243+
"-LogPath", str(self.log_path),
244+
"-UvToolDir", os.environ.get("UV_TOOL_DIR", ""),
245+
"-UvToolBinDir", os.environ.get("UV_TOOL_BIN_DIR", ""),
246+
],
247+
creationflags=subprocess.CREATE_NEW_CONSOLE,
248+
env=env,
249+
)
250+
251+
def _run_posix_fallback(self):
252+
sh_path = exc_p / "updater.sh"
253+
script = """#!/bin/sh
254+
uv_exe="$1"
255+
install_spec="$2"
256+
index_url="$3"
257+
log_path="$4"
258+
259+
"$uv_exe" tool install "$install_spec" --force --index-url "$index_url" 2>&1 | tee -a "$log_path"
260+
echo "done"
261+
printf "Press any key to close..."
262+
stty -icanon -echo
263+
dd bs=1 count=1 >/dev/null 2>&1
264+
stty icanon echo
265+
"""
266+
self._write(sh_path, script)
267+
os.chmod(sh_path, 0o755)
268+
subprocess.Popen(
269+
["setsid", "sh", str(sh_path), uv_exc, self.install_spec, self.index_url, str(self.log_path)],
270+
start_new_session=True,
271+
env=env,
272+
)
273+
274+
@staticmethod
275+
def _write(path, content: str):
276+
path.write_text(content, encoding="utf-8")

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
| [ExHentai](https://exhentai.org/) | 🌏 | 🔞/代理 | ![status_ehentai](https://img.shields.io/endpoint?url=https://cgs-status-badges.pages.dev/status_ehentai.json) |
5454
| [Hitomi](https://hitomi.la/) | 🌏 | 🔞 | ![status_hitomi](https://img.shields.io/endpoint?url=https://cgs-status-badges.pages.dev/status_hitomi.json) |
5555
| [Kemono](https://kemono.cr) | 🌏 | 🔞 | |
56-
| [HComic](https://kemono.cr) | 🌏 | 🔞/代理/`2.8.6-beta`~ | ![status_hitomi](https://img.shields.io/endpoint?url=https://cgs-status-badges.pages.dev/status_h_comic.json) |
56+
| [HComic](https://kemono.cr) | 🌏 | 🔞/代理/`2.8.6-beta.2`~ | ![status_hitomi](https://img.shields.io/endpoint?url=https://cgs-status-badges.pages.dev/status_h_comic.json) |
5757

5858
使用请适度,以免加重对方服务器负担,也减少被封ip风险
5959

assets/_pystand_static.int

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ if __name__ == '__main__':
5656
pkg_spec = pkg_spec.replace("ComicGUISpider", "ComicGUISpider[script]")
5757
install_cmd = [str(uv_exec), "tool", "install", pkg_spec, "--force"]
5858
if args.conf:
59-
install_cmd.extend(["--config-file", portable_env.joinpath(args.conf)])
59+
install_cmd = [str(uv_exec), "--config-file", portable_env.joinpath(args.conf), "tool", "install", pkg_spec, "--force"]
6060
else:
6161
install_cmd.extend(["--index-url", index_value])
6262
print(install_cmd)

deploy/installer/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "cgs-installer"
3+
version = "2.8.6"
4+
edition = "2024"
5+
6+
[[bin]]
7+
name = "installer"
8+
path = "src/main.rs"
9+
10+
[dependencies]
11+
eframe = "0.33"
12+
clap = { version = "4.5", features = ["derive"] }
13+
pep440_rs = "0.7"
14+
regex = "1.12"
15+
16+
[target.'cfg(windows)'.dependencies]
17+
windows = { version = "0.62", features = [
18+
"Win32_System_Threading",
19+
"Win32_Foundation",
20+
] }
21+
22+
[profile.release]
23+
opt-level = "z"
24+
lto = true
25+
strip = true
26+
codegen-units = 1

deploy/installer/build.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use std::env;
2+
use std::fs;
3+
use std::path::PathBuf;
4+
5+
fn main() {
6+
#[cfg(windows)]
7+
{
8+
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
9+
if target_env == "msvc" {
10+
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set"));
11+
let manifest_path = out_dir.join("installer.manifest");
12+
let manifest = r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
13+
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
14+
<assemblyIdentity type="win32" name="ComicGUISpider.Installer" version="1.0.0.0"/>
15+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
16+
<security>
17+
<requestedPrivileges>
18+
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
19+
</requestedPrivileges>
20+
</security>
21+
</trustInfo>
22+
<application xmlns="urn:schemas-microsoft-com:asm.v3">
23+
<windowsSettings>
24+
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
25+
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
26+
</windowsSettings>
27+
</application>
28+
</assembly>
29+
"#;
30+
fs::write(&manifest_path, manifest).expect("failed to write manifest");
31+
println!("cargo:rustc-link-arg-bins=/MANIFEST:EMBED");
32+
println!(
33+
"cargo:rustc-link-arg-bins=/MANIFESTINPUT:{}",
34+
manifest_path.display()
35+
);
36+
}
37+
}
38+
println!("cargo:rerun-if-changed=build.rs");
39+
}

deploy/installer/src/args.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use clap::Parser;
2+
3+
#[derive(Debug, Clone, Parser)]
4+
#[command(name = "installer", version, about = "ComicGUISpider native updater")]
5+
pub struct CliArgs {
6+
#[arg(long = "uv-exc")]
7+
pub uv_exc: String,
8+
9+
#[arg(long)]
10+
pub version: String,
11+
12+
#[arg(long = "index-url", default_value_t)]
13+
pub index_url: String,
14+
15+
#[arg(long = "parent-pid", default_value_t = 0)]
16+
pub parent_pid: u32,
17+
18+
#[arg(long = "uv-tool-dir", default_value_t)]
19+
pub uv_tool_dir: String,
20+
21+
#[arg(long = "uv-tool-bin-dir", default_value_t)]
22+
pub uv_tool_bin_dir: String,
23+
24+
#[arg(long = "no-gui")]
25+
pub no_gui: bool,
26+
}

0 commit comments

Comments
 (0)