diff --git a/apps/desktop/src/updater/update_controller.cpp b/apps/desktop/src/updater/update_controller.cpp index 9ba39f9d..124d3ca2 100644 --- a/apps/desktop/src/updater/update_controller.cpp +++ b/apps/desktop/src/updater/update_controller.cpp @@ -20,6 +20,10 @@ Controller::Controller(fs::path cache) : cache_(std::move(cache)) { state_ = State::Failed; error_ = result.value("error", std::string("Update did not complete")) + "\n" + PathUtf8(previous); + } else if (fs::exists(previous / "started")) { + // Retire receipts confirmed by older clients too, before temporary + // storage is cleaned by the OS and a successful update looks interrupted. + fs::remove(cache_ / "last-update"); } } catch (const std::exception&) {} } @@ -33,7 +37,12 @@ void Controller::ConfirmStartup() { PlatformKey(ExecutablePath()), "0.0.0"); auto built = BuildVersion(); if (!built.empty() && built[0] == 'v') built.erase(0, 1); - if (artifact.version == built) WriteText(previous / "started", "started\n"); + if (artifact.version == built) { + WriteText(previous / "started", "started\n"); + // Acknowledge the coordinator first. Successful startup no longer needs + // a persistent pointer into a temporary job directory. + fs::remove(cache_ / "last-update"); + } } catch (const std::exception&) {} } Controller::~Controller() { diff --git a/docs/UPDATER.md b/docs/UPDATER.md index f20fb19d..e2e1a669 100644 --- a/docs/UPDATER.md +++ b/docs/UPDATER.md @@ -116,8 +116,11 @@ xmake b crossdesk 下载、验签或准备失败时不关闭主程序。主程序退出后的安装失败会尝试 重启;macOS/Linux 在退出前取消授权时保留原程序和连接。 `last-update` 位于应用缓存目录,指向私有暂存目录;`request.json` 和 -`result.json` 保留升级版本及结果,未完成的任务不会自动重放。成功启动后 -删除大型安装包,保留少量诊断文件。失败任务保留下载包便于排查。 +`result.json` 保留升级版本及结果,未完成的任务不会自动重放。新版本确认 +启动后先通知升级器,再清除 `last-update`,避免临时目录被系统清理后 +误报升级中断;旧客户端已经确认成功的记录也会在下次启动时清除。 +升级器随后删除大型安装包,保留少量诊断文件。失败任务保留记录和下载包 +便于排查。 NSIS、PKG 和 DEB 的安装操作不是跨平台事务。当前没有自动回滚承诺: 安装中断或新版本启动失败时,保留错误并提供手动修复安装路径。不能通过