更新和回滚
桌面版的更新是一个事务:检查 → 决定 → 下载 → 校验 → 停运行时 → 备份 → 解包 → 用新版本迁移数据 → 自检 → 换指针 → 启动。任何一步失败,数据从备份恢复,指针不动。
安装目录
<安装目录>/
versions/<build>/ 解好、校验过的各个版本(并排放,不原地覆盖)
current.json 指针:现在用哪个(原子替换)
previous.json 指针:上一个(回滚用)
staging/<build>.partial/ 正在解的(没解完的永远不会被当成一个版本)
downloads/ 下载中的和下完校验过的包
从源码跑的开发环境没有这个目录,更新也不作用在它上面。
一次安装
- 检查:读签名的发布清单(从 GitHub Releases 找,3.28),验签。
- 决定:可选更新,用户可以现在装、明天再提醒、跳过这一版;装着的版本低于「最低安全版本」或者被撤回,就是强制更新。
- 下载、校验:边复制边算哈希,复制进只有自己能读写的暂存区,解压的是这份副本。
- 解包:绝对路径、
..、符号链接 / 硬链接、设备文件、超出总量和文件数上限,一律拒绝;包里的构建信息和清单对上了,才改名成versions/<build>。 - 备份、迁移(用新版本自己跑
aeria migrate --root <数据目录>)、自检(aeria self-test --root <数据目录> --json)。 - 提交:换
current.json,重启运行时。
整个过程写在一份事务日志里;中途断电,下一次收尾(aeria update recover)按日志处理:指针还没换的,数据从这次的备份恢复,旧版本照旧;指针已经换了的,就是装好了。安装、收尾、回滚拿同一把跨进程的锁。
安全模式
运行时一启动先看本地缓存的、验过签的策略(不联网):这个版本低于最低安全版本、或者被撤回,就不启动人格、插件,退出码告诉桌面版进安全模式(只能更新、备份、导出、诊断)。上一次安装改数据改到一半、还没收尾,也不启动。
拿不到策略(从没检查过、断网、签名不对、缓存被改过)就照常运行;缓存里有一份验过签、说它不安全的,断网也不放行。
回到上一个版本
只换程序、不动数据:把 previous.json 换回来,之后固定用它,直到再装新的。数据也要回去,就恢复更新前自动做的那一份备份。
对应的代码
- 目录和解包:
src/aeria/update/layout.py(safe_extract);事务:src/aeria/update/service.py;安全模式:src/aeria/update/safe_mode.py(SAFE_MODE_EXIT_CODE);迁移和自检:src/aeria/update/runtime_commands.py;命令:src/aeria/update/cli.py(aeria update …)。 - 去哪找新版本:
src/aeria_release/providers.py的GitHubReleasesProvider。 - 测试:
tests/test_4_1_update.py的「迁移失败,数据从备份恢复,指针不动」「签名不对的清单不收」「包和清单对不上,不装」「恶意包:越界路径、链接、设备文件一律拒绝」。
没做到的
- 更新是整包换:没有只下改动部分的增量更新。
- 官方仓库还没公开,第一个公开版本也还没发:更新这条路在真的发布渠道上还没走过一遍。