Repository navigation
Releases: charsen/moo-git-fleet
Release list
Moo Fleet 0.2.0
Moo Fleet 0.2.0 —— 勾选的新文件可以整批删掉,工作区操作快了一倍
0.1.51 修的是弹窗被拖拽误关。这一版换了个方向:把工作区里最容易卡手的一件事补上,顺带把每次文件操作都要跑一遍的全量扫描砍掉。
一、勾选的新文件可以整批删除
临时生成的探针脚本、构建残留、调试用的假数据——这类文件被勾进暂存区之后,想整批丢掉,以前只能一个个取消暂存、再一个个删。
现在:勾选一批从未提交过的新文件后,分组标题栏出现「删除 N 个」。确认后取消暂存并把整批文件移入系统废纸篓,一个动作结束。
两个边界值得说明:
- 判据是「未跟踪」或「索引状态为新增」,不是只看未跟踪。勾选本身就是
git add,勾完之后untracked就不再为真了——只看它会漏掉整整一类文件。这个判定放在src/shared/file-status.ts,客户端和服务端共用同一份,不会出现两边判断不一致。 - 勾选里混入已跟踪文件时,整批不给入口。 已跟踪文件的删除是「丢弃改动」的语义,和「删掉这个新文件」不是一回事,混在一起做容易出事。冲突文件由服务端整体拒绝,而且校验跑在任何写入之前——不会出现删了一半才发现有冲突。
服务端只回文件清单,废纸篓在四个平台上整批一次调用;只有整批失败时才逐个重试,用来定位到底是哪个文件挡住了。
二、工作区操作快了一倍
本机 20 仓合成舰队实测:
| 操作 | 0.1.51 | 0.2.0 |
|---|---|---|
| 暂存 | 46–64 ms | 25 ms |
| 取消暂存 | 37–39 ms | 17 ms |
| 文件列表 | 20 ms | 10 ms |
| 仪表盘 | 115 ms | 95 ms(1.5 s 内的重复调用 0.7–1.3 ms) |
做法是去掉重复劳动,没有引入缓存一致性的妥协:
- 暂存、取消暂存、忽略、取消忽略、assume-unchanged 这六个接口里,每次都调用
scanRepository做全量扫描,但调用方从不读它的返回值。删掉。(/hunks和冲突解决确实在用status,保留。) - 文件列表用
.git存在性快检替代每请求一次的git rev-parse --show-toplevel;只有.git缺失时才回退到 git,两种报错文案都保住了。 - 仓库配置按
(mtime, size)缓存解析结果并返回克隆,配置没变就不重复解析。 - 判断仓库内部状态时直接读
.git(目录或gitdir:文件),每个仓库少起一个 git 进程。.git文件里的路径可以含换行,所以只按前缀切一次、去掉结尾换行,不按行切。 - 客户端五处文件动作改用
scheduleStageRefresh(),忙态不再被一次全量扫描拖住。
仪表盘的结果缓存键带 scanGeneration,任何写操作都会击穿缓存,不会读到过期数据。
三、这一版还包含(内部改动,不影响使用)
- 构建脚本不会再覆盖已发布的 DMG。 以前同版本重建会先无条件删掉同名 DMG,等于把已经发出去的那份一起删了。现在先比对
release/Moo-Fleet-<ver>-artifacts.json里的 sha256,一致(= 就是发出去的那一个)就先挪到release/.published/留档,再照常清理。 - 批量删除有了独立真机验收脚本(
npm run verify:ui:batch,27 项断言),覆盖基线、两种视口宽度、混合选中反例、确认弹窗、取消,以及删除之后的五方对账(提示语 / 列表 / 磁盘 / 索引 / 系统废纸篓)。两处变异测试确认断言不是空转。 - 修掉了真机套件里「Esc 关抽屉」长期失败的真因。 不是产品 bug——是套件自己在阶段 6 打开管理弹窗后忘了关,之后抽屉开在弹窗上面,而全局 Esc 从最上层往下关,每次都先去关那个看不见的弹窗。断言现在改成「必须由 Esc 关闭」,靠关闭按钮兜底算失败。
四、下载哪个
macOS:
| 芯片 | 文件 | 大小 |
|---|---|---|
| Apple Silicon(M 系列) | Moo-Fleet-0.2.0-macos-arm64.dmg |
44.3 MiB |
| Intel | Moo-Fleet-0.2.0-macos-x64.dmg |
46.5 MiB |
两个 DMG 都是 Developer ID 签名 + Apple 公证 + 票据已 staple:双击挂载、把 App 拖进「应用程序」、双击打开即可,不需要右键打开,也不需要 xattr 清除隔离属性。
Linux:
| 包 | 文件 | 大小 |
|---|---|---|
| Debian / Ubuntu | Moo-Fleet-0.2.0-linux-amd64.deb |
95.1 MiB |
| 通用(AppImage) | Moo-Fleet-0.2.0-linux-x86_64.AppImage |
94.5 MiB |
Windows:
| 包 | 文件 | 大小 | 在哪 |
|---|---|---|---|
| 安装版(NSIS) | Moo-Fleet-0.2.0-windows-x64-setup.exe |
107.6 MiB | 仅 GitHub |
| 免安装 | Moo-Fleet-0.2.0-windows-x64.exe |
97.6 MiB | GitHub |
Windows 安装版超过了 Gitee 单文件 100 MiB 的上限,所以只在 GitHub 发布;Gitee 上放了 Linux 两件。
Windows 两件没有 Authenticode 签名,首次运行 SmartScreen 会提示「未知发布者」,点「更多信息 → 仍要运行」即可。这一点和之前的 Windows 包一致。
五、验证
npm run typecheck通过(vue-tsc+ 服务端tsc)。- 单元测试 128 文件 / 1270 项全部通过(单 worker,发版口径)。
- 真机 UI 断言 393 项全部通过,跑的是打包产物(
release/macos-arm64/Moo Fleet.app内嵌服务端,不是开发实例),控制台 0 error、0 未捕获异常。 - 批量删除专项 27 项全部通过,并做过两次变异测试(去掉混合选中守卫 → 恰好 1 项失败;判定退回只看
untracked→ 11 项连环失败),确认断言不是空转。 - 两个 DMG:
codesign --verify --deep --strict通过,flags=0x10000(runtime),带安全时间戳(arm64Oct 30, 2026 at 20:29:55、x64Oct 30, 2026 at 20:36:11),stapler validate与hdiutil verify均通过。 - 包内
Info.plist:0.2.0 / build 200 /com.mooeen.fleet,两个架构一致。 - Linux 两件:deb 的
Package/Version/Architecture为moo-fleet-desktop/0.2.0/amd64,ar三段成员完整;AppImage 是 ELF 可执行 +AI\x02魔数,SquashFS 从第 32,609 字节起(外壳在前)。 - Windows 两件:PE 头(
MZ+PE\0\0)正确,版本串0.2.0与产品名都在资源里;两件均未做 Authenticode 签名(与之前的 Windows 包一致)。
六、校验和
f80b4e29f29c9ec23253010ff0ad495685c912781f2c76184adb94595224a3df Moo-Fleet-0.2.0-macos-arm64.dmg
f3cbb65dcbc19d4f402c6cf06e6607da0bc1cb9fb821ce7af876c61cf7a05650 Moo-Fleet-0.2.0-macos-x64.dmg
4a608a7130f7fce97db05794c7f7dfb9acd47d01c9ca8cf2d253364d606c4d60 Moo-Fleet-0.2.0-linux-amd64.deb
64084714d579b566ed6e9681e65223f650b7099276f0d4553bafe4cf3b9fd0ad Moo-Fleet-0.2.0-linux-x86_64.AppImage
184fb2408c3cf502dc1a7d00d495d0bbf33eecb8d4d14ee6b811e73789300796 Moo-Fleet-0.2.0-windows-x64-setup.exe
7d1d4a0a02d374d569e81d5f35be7b46982b44fe5bd4eab2986bcf59b1b1c69d Moo-Fleet-0.2.0-windows-x64.exe
七、没做的事
- 没跑真实安装门禁(
npm run test:mac-install-e2e)。它会退出 App、挂载镜像并操作/Applications,需要单独授权。 - 没做跨机 Gatekeeper 验收。 本机 Gatekeeper 是关的(
assessments disabled),本地spctl通过只证明票据存在,不代表另一台干净机器上首次打开不会被拦。 - Windows 两件未做 Authenticode 签名(需要
CSC_LINK与CSC_KEY_PASSWORD,当前未配置)。 - Linux / Windows 包只做了包结构与版本校验,没有在真机 Linux / Windows 上跑过。
Moo Fleet 0.1.51 —— 弹窗不再被拖拽误关
Moo Fleet 0.1.51 —— 弹窗不再被拖拽误关
这一版只有一处功能修复,但它影响七个弹窗,而且触发方式非常容易撞上:在弹窗里按住鼠标选字,往窗口外一拖再松手,弹窗就关了,没保存的编辑一起丢。
一、按住鼠标一拖,弹窗就没了
受影响的是「快捷键」「管理仓库」「编辑仓库配置」「upstream 修复」「确认框」「克隆仓库」「合并分支」这七个弹窗。
原因是判断「是不是点了遮罩外部」用的办法不对。旧实现看的是点击事件的 self——只有事件目标正好是遮罩本身才算「点外部」。可浏览器的 click 目标不是按下点,而是按下点与松开点的最近公共祖先。弹窗是遮罩的子节点,所以在弹窗里按下、拖到遮罩上松手,这个公共祖先正好是遮罩,于是这次手势被当成了「点了外部」。
在有输入框的弹窗里选一段文字复制,几乎每次都会触发。
现在改成「按下、松开、点击三者都落在遮罩上」才关闭。按下点用捕获阶段记录,弹窗内部即使阻止事件冒泡也藏不住「按下点在弹窗里」这个事实。真正点遮罩仍然照常关闭,不会因为修这个把正常行为改坏。
二、仓库列表:选中文字不再顶开抽屉
同一类问题的另一面。仓库行本身是可点击的(点一下打开右侧抽屉),而仓库名和路径都是可选文字。按下点和松开点都在同一行里,浏览器照样派发一次 click,于是「选中路径准备复制」被当成「点了这一行」。
现在行点击会先看一眼:这一行里有没有非空选区?有就忽略这次点击。点别处时浏览器会先收掉选区,所以正常点击不受影响。
三、这一版还包含(内部改动,不影响使用)
- 公证被拒时,构建脚本会自动按 submission id 拉取
notarytool log并打印具体问题,不再只丢一句did not pass。 - 签名与公证的操作手册补全了私钥备份、换机恢复、证书到期与续期陷阱几节。
- 真实安装门禁现在能跑签名分发包(详见下面「没做的事」)。
四、下载哪个
macOS:
| 芯片 | 文件 |
|---|---|
| Apple Silicon(M 系列) | Moo-Fleet-0.1.51-macos-arm64.dmg(44.3 MiB) |
| Intel | Moo-Fleet-0.1.51-macos-x64.dmg(46.5 MiB) |
两个 DMG 都是 Developer ID 签名 + Apple 公证 + 票据已 staple:双击挂载、把 App 拖进「应用程序」、双击打开即可,不需要右键打开,也不需要 xattr 清除隔离属性。
Linux:
| 包 | 文件 |
|---|---|
| Debian / Ubuntu | Moo-Fleet-0.1.51-linux-amd64.deb(95.1 MiB) |
| 通用(AppImage) | Moo-Fleet-0.1.51-linux-x86_64.AppImage(94.5 MiB) |
这一版没有 Windows 包。 Windows 桌面包上次构建是 0.1.49,本次没有重新构建,需要的话去 v0.1.49 取(Windows 安装版只在 GitHub 发布,Gitee 上因为单文件 100 MiB 上限没有)。
五、验证
- 单元测试 128 文件 / 1256 项全部通过(单 worker,发版口径)。
- 真机 UI 断言 392 项全部通过,其中新增两组就是针对本版这两处修复,且两组都做过反向实验:把修复临时改回去,对应断言会失败;改回来再跑通过。
- 两个 DMG:
codesign --verify --deep --strict通过,flags=0x10000(runtime),带安全时间戳Oct 29, 2026 at 10:40:20,stapler validate与hdiutil verify均通过。 - 包内
Info.plist:0.1.51 / build 151 /com.mooeen.fleet,两个架构一致。 - Linux 两件:deb 的 control 版本、架构、desktop entry、图标对齐等 13 项检查通过;AppImage 的 SquashFS、AppRun、外壳与服务端 bundle 等 9 项检查通过。
- 真实安装门禁:arm64 与 x64 各跑一轮,干净安装、递归 quarantine、升级保留配置三回通过,最终安装到
/Applications的候选通过签名校验与健康检查。
六、校验和
df48f819d0ffaa362fe1c552ab2b41886fc0843b6d16943cbe1be91bd53c1797 Moo-Fleet-0.1.51-macos-arm64.dmg
9c2b2d470a903355e653974a59eafbbaa33d7b98a5d26be8249bcf7c62eeb9ae Moo-Fleet-0.1.51-macos-x64.dmg
358ae7c3147350b21c88c7d2f5816030474197968a06eee39e699582a18d98a1 Moo-Fleet-0.1.51-linux-amd64.deb
5f4c5ed659839d277a4a26a9dc029b5e637c95f6ec8649c78ff76d51779cc0e4 Moo-Fleet-0.1.51-linux-x86_64.AppImage
同 SHA256SUMS-0.1.51.txt。下载后核对一遍:
shasum -a 256 -c SHA256SUMS-0.1.51.txt七、没做的事
- 没有在另一台干净机器上验收。 构建机的 Gatekeeper 评估是关闭的(
spctl输出里override=security disabled),本机的accepted只能证明票据存在,不能证明别人电脑上双击就开。这一条仍未实测。 - 安装门禁的第 4、5 回对签名包不适用。 「运行中的 App 拒绝被覆盖」和「安装锁冲突」是内测辅助安装器的机制,签名分发包不带安装器、用户是拖拽安装,这两回在语义上不存在。门禁现在按包类型自动选模式,这两回会显式跳过并打印原因,不做假通过。
- x64 的隔离副本启动断言在这台机器上跳过。 Apple Silicon 上经 Rosetta 运行带隔离属性的 x86_64 副本时,系统既不启动也不报错(转译前就被拦住);同一份包去掉隔离属性立刻正常。这是宿主限制,签名与票据断言仍然照做。
- Developer ID 证书有效期到 2027-02-01,被 Apple 的 Developer ID CA 根证书卡住,不是一年一续。到期前要换新证书并重新公证,续期时必须让签发者带
OU=G2,否则新证书会和旧证书同一天失效。
Moo Fleet 0.1.50 —— 首个签名并公证的 macOS 发行版
Moo Fleet 0.1.50 —— 首个签名并公证的 macOS 发行版
这一版没有功能变化。 与 0.1.49 相比,改的只有两件事:应用的身份(包名),以及它的签名方式。
但这两件事都会让你在升级时看到明显不同的行为,所以值得单独发一版。
一、包名从 com.mooeen.moofleet 改成 com.mooeen.fleet
这不是重命名癖。三个自研 macOS 项目(Moo Fleet、小光语、RDM)此前各用各的前缀,
现在统一收到 com.mooeen.* 下,将来做统一签名、统一分发、统一更新时才不会各踩各的坑。
代价是:对 macOS 来说,这等于换了一个 App。
- 偏好设置会重置一次。 窗口位置、主题、上次打开的页签都记在包名下面,
换了包名就是新的存储域。旧的那份还在(com.mooeen.moofleet),但没有代码再读它。 - 辅助功能授权要重新授予。 系统按包名记录这类授权,旧授权不会跟过来。
- 如果你之前在「登录项」里加过它,那一项会指向一个已经不存在的 App,删掉重加即可。
这三条都只发生一次。往后包名不会再动——发出去就改不了了。
二、首次打开不需要任何额外操作
0.1.49 及更早的 macOS 包是 ad-hoc 签名的,没有经过 Apple 公证。那种包在别人电脑上
第一次打开时会被 Gatekeeper 拦下,提示「已损坏」或「无法验证开发者」,得右键→打开,
或者跑一句 xattr -dr com.apple.quarantine。
现在两个 DMG 都是 Developer ID 签名 + Apple 公证 + 票据已 staple:
$ spctl -a -vv Moo-Fleet-0.1.50-macos-arm64.dmg
Moo-Fleet-0.1.50-macos-arm64.dmg: accepted
source=Notarized Developer ID
origin=Developer ID Application: Charsen Fung (S967RUU99W)
双击挂载、把 App 拖进「应用程序」、双击打开。就这样。那条 xattr 命令和右键打开的说明
从这一版起作废——对已公证的包还教用户绕过 Gatekeeper,反而是在教错东西。
公证是按包内容做的,App 内的 runtime/node 也一并签了名并带着 allow-jit 权限
(硬化运行时会禁掉 JIT,缺这条权限 Node 根本起不来)。
三、下载哪个
| 芯片 | 文件 |
|---|---|
| Apple Silicon(M 系列) | Moo-Fleet-0.1.50-macos-arm64.dmg |
| Intel | Moo-Fleet-0.1.50-macos-x64.dmg |
两个都是 46–49 MB。选错了也打得开(macOS 会提示架构不符),但别选错。
这一版只出了 macOS 包。 Windows 与 Linux 的桌面包没有重新构建,0.1.49 的那几个仍然可用,
需要的话去 v0.1.49 取。
四、验证
- 两个 DMG 均通过
codesign --verify --strict、stapler validate,spctl判定
source=Notarized Developer ID。 - 挂载 DMG 后对包内副本再验一次 staple,确认票据是随包走的,不是只留在本机那份
.app上。 - 包内
Info.plist:版本 0.1.50 / build 150 /com.mooeen.fleet;主程序与内嵌 node 架构与包名一致。 - 构建流程内置了一道执行检查:签完名的
runtime/node --version必须仍能跑起来并报出预期版本,
否则构建直接失败——签名把运行时弄坏这种事,不该等到用户双击才发现。
五、校验和
921c34fd9ff79b41b1737c77e836599eb3f13597f6f2e5d789f3696cabf68941 Moo-Fleet-0.1.50-macos-arm64.dmg
e766878925149fb1370ef6458a805c06f9fb4eaa0623cd5cbb8d968bdcf4b8af Moo-Fleet-0.1.50-macos-x64.dmg
同 SHA256SUMS-0.1.50.txt。下载后核对一遍:
shasum -a 256 -c SHA256SUMS-0.1.50.txt六、没做的事
- 没有在另一台干净机器上验收。 构建机的 Gatekeeper 评估是关闭的(
spctl输出里
override=security disabled),所以本机的accepted只能证明票据存在,不能证明
别人电脑上双击就开。这一条还得实测。 - Developer ID 证书的有效期到 2027-02-01(被 Apple 的 Developer ID CA 根证书卡住,
不是一年)。到期前要换新证书并重新公证,否则之后的包会退回未公证状态。
Moo Fleet 0.1.49
Windows 安装版请到 GitHub 下载。
Moo-Fleet-0.1.49-windows-x64-setup.exe(107.9 MiB)超过 Gitee 单个附件 100 MiB 的上限,Gitee 上没有这个文件,上传会被平台直接拒绝。需要 NSIS 安装版请到 GitHub Releases · v0.1.49 取;Gitee 侧提供的是功能一致的免安装便携版Moo-Fleet-0.1.49-windows-x64.exe。其余平台包两边完全一致,哈希见SHA256SUMS-desktop-0.1.49.txt。
本次更新
这一版只有两件事:把消息放回它该在的地方,以及修掉十个「看着像偶发、其实必然」的坑。没有新功能。
一、消息不再弹在屏幕角上
以前一次批量 Fetch 会弹两条浮层提示,最响的那条(实心绿条 + 倒计时)说的只是按钮上已经写着的数字:一个 680×69 的绿条盖在内容上,承诺几秒后自己消失,而触发它的按钮在另一个角落。上一版把它挪到右下角,仍然是浮层——问题不在位置。
根子在通道。 全应用 129 处提示共用一个变量,落点靠「此刻开着哪个面板」猜:同一句话在抽屉里出现一次,关掉抽屉跳到舰队页又一次,再开设置出现在弹窗页脚上方。为此写了 5 处「换容器就清空」的补丁,代价是切一下页签回来就看不到刚才那句。
现在每条消息带一个归属:它属于某个工作区、某个仓库、设置页,或者某一批操作。归属决定它落在哪,与你现在开着哪个面板无关——所以「换容器时清空」整套补丁消失了,切页签也不再丢话。
- 成功消息落到各自面板里,贴边一行细字,只有图标带状态色,不占浮层、不压内容、没有倒计时。
- 关掉的容器不搬消息,在入口点挂一个小圆点。
- 后台操作永远不抢用户的话:进行中可以接替进行中,但接替不了一条你还没看过的回执。
- 抽屉标题就写着仓库名,消息里的
${仓库名}:前缀删掉了(35 处);跨仓库与设置场景保留。
二、删掉的会话不会再自己回来
你在这台电脑上删掉一条会话,提示说「已移到系统废纸篓 · 备份保持不变」,几小时后同步报「恢复 1 条」——那条会话带着继续命令回来了。
原因是「备份里有、本机没有」被一律当成「另一台电脑的会话」,而它也可能是你刚删的。现在本机记住这个删除(存在本机配置里,不进备份仓——它是这台电脑的偏好),下次同步跳过它,并说明可从废纸篓找回。文件被捞回来、或同名会话重新出现时,这条记录自动作废。跨机删除仍走墓碑,另一台会正常询问。
三、同步前先认这目录还归不归我
备份目录只是一次性绑定,目录本身会被换掉。如果把它挪走、在同一路径 git init 了别的仓库,下一次同步会对你的仓库执行 reset --hard、clean -fd,再逐个删掉白名单之外的顶层目录。
现在每次同步、每次处理冲突,在动这些命令之前都先核对所有权,认不出就停手并说明「没有动它」。你遇到的是报错,不是数据丢失。
四、macOS 13 / 14 上「移到废纸篓」不再失败
系统自带的 trash 命令是 macOS 15 才有的,而本应用声明支持 13.5。在 13/14 上,丢弃改动、删除会话这两条主路径都会直接报 ENOENT。现在按可用性选:有系统命令就用它,没有就通过系统接口把文件移进同一个废纸篓(可还原、不经过 Finder、不弹授权框)。文件名里的引号也不可能改写命令——路径是参数传入的,不拼进脚本。
五、「已同步」现在只在真的同步完时说
一次同步是两件事:本机备好了、远端推上去了。原来只记一个错误字段,于是远端推送失败(断网、凭证过期、非快进被拒)时,状态卡继续显示「会话已同步」,另一台电脑其实拿不到。
现在本机与远端各记一个结果:整次失败时红,只有远端没上去时黄,写明「已备份在本机,还没上传」。恢复联网后的下一次同步会清掉。
六、勾了「自动 Stash」之后出错,改动回到工作区
原来只有「分支或 HEAD 变了」这一条路径会把 stash 还回来。Fetch 断网、复校发现工作区被改过,这两类直接抛错——改动留在 stash 里,而报错只说「Fetch 失败」,既没说改动去哪了,也没提 stash 名字。
现在这些路径统一先 pop 再抛错;pop 也失败时,错误消息里明说「改动仍在 Stash 列表」。同步的推送段同理:合并已经落库、stash 还在,推失败更要还原。
七、几个「点下去没反应」的地方
- 操作记录里的「重试」丢选项。 文案写着「可勾选 rebase」「可勾选自动 Stash」,确认框里一个勾选框都没有:用 Rebase 的人重试一次会静默变成 merge,历史里凭空多一个合并提交;靠自动 Stash 才拉下来的人,重试会再撞一次「工作区不干净」。现在两个勾选框按操作类型与工作区状态出现,值真正传下去。
- amend 跑到一半,暂存和提交按钮还能点。 点下去只换来一句「已有 Git 操作正在执行」。历史改写与 revert / cherry-pick 的忙态补齐到三处禁用判断里。
- 后台刷新只刷文件与分支。 左侧「Stash 备份 N」来自整页扫描,会自己变,列表不刷就是「计数 4、列表 3」;在终端
pop掉一条之后,列表里那条还在,点「应用」只报 ref 不存在。15 秒静默刷新现在带上 Stash 与标签(标签不重复探测远端)。 - 暂存没有复核快照。 丢弃改动会先核对文件指纹,暂存不会:编辑器保存、构建产物、另一个终端 checkout 之后,你暂存到的可能是没在 diff 里看过的内容。现在两条路径口径一致,过期快照返回 409;顺带挡住冲突文件——
git add会把未合并条目直接标成「已解决」,那是解决冲突,不是暂存。 - 冲突决策用的是旧快照。 隔十几分钟才点「用另一台电脑的」,那期间新写的内容会被整份覆盖。现在决策前先取一次远端;覆盖前把本机那份移进废纸篓(内容相同则不动),并说明这件事。
八、验收脚本不再按星期几算命
这条不影响你使用,但影响我们判断「是不是坏了」。
三条断言长期红着、被当成「已知基线」:日柱比天数少 6–7 根、45 天只画 40 根、热力图 ↑ 在周一不动。查清后是两类错:
- 断言在按星期几算命。 报告窗口的结束日是本周周日(未来日期),而图表只画已经发生的日子。同一个正确实现,周一 85 根、周二 86、周日才 91。原来写死
88..92,等于要求「今天是周五以后」。 - 把刻意设计当成缺陷。 「周一按 ↑ 不动」是 10 月 24 日就定下的:上下键是「同列内换行」,跨列那一跳是上一列最后一行到这一列第一行,视觉距离最远。代码、注释、单测三处一致,是设计。改的是断言。
现在断言按「窗口起点 → min(终点, 今天)」精确算,并单独钉首尾日期;键盘断言按光标所在那天分支。verify:ui 387 项全绿、0 失败,以后它变红就是真出问题。
另外修掉一处真缺陷:本地存储里若存了填反的起止日期,图表会拿到 start > end 的窗口,一天都画不出来、页面是空图且不报错。
九、桌面版安装包(Windows / Linux)
本版与 macOS 一同提供 Windows 与 Linux 安装包,三者用的是同一份前端与服务端载荷:dist/server/index.cjs(1.14 MB)与 dist/client 全部 39 个文件,跟 macOS 包内逐字节同哈希。
| 平台 | 文件 | 说明 |
|---|---|---|
| Windows | Moo-Fleet-0.1.49-windows-x64-setup.exe |
NSIS 安装版,可选安装目录,创建桌面与开始菜单快捷方式 |
| Windows | Moo-Fleet-0.1.49-windows-x64.exe |
便携版,免安装,双击即用 |
| Linux | Moo-Fleet-0.1.49-linux-amd64.deb |
Debian / Ubuntu(amd64),依赖见包内 control |
| Linux | Moo-Fleet-0.1.49-linux-x86_64.AppImage |
通用,chmod +x 后直接运行,不依赖系统库版本 |
Gitee 上少一个文件是正常的:Gitee 单个附件上限 100 MiB,NSIS 安装版 107.9 MiB 传不上去,只在 GitHub 发布;Gitee 侧提供免安装的便携版,功能一致。其余三个包两边都有。要 Windows 安装版,直接去 GitHub Releases · v0.1.49 下 Moo-Fleet-0.1.49-windows-x64-setup.exe。
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- Windows 两个包未做 Authenticode 签名(没有证书),首次运行会被 SmartScreen 拦一次,需要「更多信息 → 仍要运行」。Linux 没有系统级代码签名机制,核对
SHA256SUMS-desktop-0.1.49.txt即可。 - 本版没有新增遥测。分析页只读本机 git 仓库,不发任何网络请求。
- 会话删除「只在这台电脑忽略」的记录存在
config/session-ignores.json,不进备份仓;想让它重新同步,删掉对应条目即可。
验证
- 类型检查、
vue-tsc、ESLint 与生产构建全部通过;126 个文件 / 1245 个用例全绿。 - macOS 包已装进
/Applications实跑:0.1.49 / build 149、arm64、隔离属性 0 处、codesign通过、窗口完整渲染(仓库 54、待推送 2、待拉取 4),7 个只读接口全 200,日志无错。 - 桌面版载荷逐个解包核对:deb 的
control版本 0.1.49、win-unpacked/linux-unpacked内package.json均为 0.1.49,服务端 bundle 哈希与本地构建一致,客户端 39 个文件零差异。 - 界面断言 387 项(真机跑,全部通过):消息归属 4 条与抽屉归属 6 条、暂存快照 2 条、键盘可达性、日柱窗口边界。
- 变异验证(确认断言真的会拦):删掉同步前的所有权检查 → 「同步被拒绝」挂;
/stage退回只做 id 转换 → 「过期快照应 409」挂;冲突守卫改if (false && …)→ 「冲突不允许暂存」挂;stash 还原改回裸throw→ 「改动必须回到工作区」挂;热力图不画未来日期这一条改回画 → 恰好 4 条新断言挂、其余不动;窗口读回不归位 → 反向区间用例挂。 - 已实测的反例:
git 2.54上「空仓库取消暂存必失败」不成立(git init后add再reset --退出码 0),所以这条没有改动。
Moo Fleet 0.1.48
本次更新
先说一件事:上一版 0.1.47 只推了 tag、没有创建 Release,安装包从未分发出去。所以这份说明同时覆盖它——从 0.1.46 直接升上来的用户,会一次拿到两版的全部改动。
一、0.1.47 带来但此前没有发出的部分
卡片底色单独一档
页面级卡片(统计卡、图表卡)原来直接借了浮层的颜色。在深色主题上它比画布亮 1.26:1——单看一张卡没问题,满屏十几张大色块一起亮,整页就发白。现在把层次拆成四档:画布 < 卡片 < 轨道 < 浮层。卡片只比画布抬 7–9 个色阶(VS Code 深色主题从 #2b2b2b 收到 #212121,1.26:1 → 1.10:1),层次靠 1px 边界划,不靠亮度堆。进度轨道也不再借用「悬停色」——静态元素顶着一层 hover 色会比卡片本身还亮。
标题栏跟着主题走
macOS 窗口的标题栏是透明的,透出的是窗口自己的底色。这个颜色原来写死成 fleet-blue 的深蓝,切到其他四套主题,顶上就挂着一条不搭的蓝带。现在启动时读 config/profile.yaml 里的主题;运行时切换主题,网页会把导航色与画布色的计算值回传给原生窗口,标题栏立刻跟着变,不用重启。
热力图:骨架屏与日柱
冷启动有了骨架屏。 全量扫描要十几秒,原来这期间图上该在的位置是空白。现在按真实排版摆占位:标题、图例、网格、四张统计卡;网格用 SVG pattern 铺,不生成几百个占位节点。量过:骨架 385px 对真实首屏 411px,数据到了不会跳一下。
半年内一天一根柱子。 日柱上限从 91 天放到 183 天:近 6 个月按天分槽铺满整幅(181 根,柱宽 4.6px),高度恒定在 295–317,换时间段不再把卡片撑高或压扁。超过半年才回到 7 行网格。
时间段时间可以自选
除了近 3/6 个月、近一年、近两年,还能直接选日期区间;排行度量收成整页唯一的开关,走到哪都跟着。
二、点下去被吞掉的那几下
勾完一个文件,立刻点下一个,那次点击会被忽略。 原来的忙态用了「包含暂存自己」的那一个,于是文件刚勾上、暂存请求还没回来,下一个文件的点击判定就被挡掉了。现在只挡真正在改索引的操作,同一份判断在按钮和键盘空格上共用。实测同一个动作:修复前 525 ms 后选中的仍是上一个文件,修复后 107 ms。
按块暂存的按钮会整排消失。 操作条在忙态下被整体移出 DOM,用户看到的是「按钮没了 215 ms 又回来了」,块上的转圈反而是死代码。现在拆成两个信号:「这一块正在执行」(保留元素、显示转圈、禁用)和「有别的写操作在跑」(禁用但保留元素)。空窗降到约 60 ms,剩下的部分是 diff 确实要重读。
预览 diff 不该占着仓库锁。 原来打开预览会让后续的暂存、勾选被判成「操作正在执行」,连续操作全被拒。预览是只读的,现在不再取锁;一致性由预览前后的指纹比对 + GIT_OPTIONAL_LOCKS=0 保证。顺带摘掉了 10 处「预览打开就不许动」的守卫——那些守卫在预览关掉后没被清,表现为之后连续操作静默失效。
提交中切到别的仓库,工作台会永久禁用。 一个忙态只在「还在同一个仓库」时才清;一旦切走,条件永不成立,而暂存、提交、按块、Fetch 全都在等它。现在纳入切仓库时的统一重置,并加了一条结构性断言:解析三处禁用判断的表达式、取出里面所有忙态,要求每一个都出现在重置清单里,以后新增忙态漏了会直接失败。
前台加载会被 15 秒的后台刷新顶掉,然后一直灰着。 原来的落旗判据是「请求序号还是最新的吗」,前提是「只有前台请求会推进序号」;后台静默刷新一插队,前台那次返回时判据不成立、整段跳过,而后台那一路本来就不动加载态,旗子永久为真。改成按「还有几个前台请求在跑」计数,后台不参与——它本来就不该有资格关掉前台打开的旗。
主题来回切会丢最后一次。 保存队列原来在排队那一刻就拿快照比较「和已保存的一样吗」,改回原值这一次被判成重复而跳过,先前那次请求随后落库,服务端和本地缓存从此不一致(下次启动会自己变回去)。现在排队只记目标值、落库后再比。
三、服务端少做重复功
- 去掉每次请求都重跑的 git 全量扫描与串行读取,仓库列表与文件清单共用一次结果。
- 会话备份的说明文件改为并发读,不再一条一条串着等。
upstream修复方案不再为每个分支各算一次领先/落后。- 写请求共享在途的会话令牌请求,不再并发重复取。
- dashboard 查询的刷新间隔对齐轮询周期,窗口重新可见时不再额外全量重扫。
四、热力图的提示框
鼠标停在一格上,用触控板横向滚动:指针没动、格子换天了,mouseleave 不会触发,固定在视口坐标上的提示就冻在原地不走。现在三处收口——窗口捕获阶段的滚动、两张图各自的移出、以及 mousemove 时校验指针是否仍在数据元素上。键盘聚焦后离开图表同样会收起。
五、看不清的选中态
时间段按钮与排行口径按钮共用一套样式,选中项原来只靠一档底色压在槽底上。五套主题实测对比度只有 1.06 / 1.07 / 1.07 / 1.32 / 1.11,12px 的字上等于没有。往上再提亮就会跟卡片、浮层抢重量,所以同时补了一圈内描边:底色负责「有块面」,描边负责「到哪为止」。一处改动,两处控件都受益。
六、把边界说清楚
- 仓库范围多选在筛选状态下,「全选」写成「全选(共 53 项)」——不写范围时,筛成 3 条却选中 53 条是误导。行为不变。
- 搜索结果的折叠现在真的生效(原来点了没反应,清掉搜索才突然展开/收起)。
- 会话页后台每 30 秒的静默刷新失败,不再把整张列表换成错误页——只在手头没有内容时才让错误页接管。
- 两处读屏播报的噪音收掉了:顶栏 API 状态原来每 15 秒播一次「一切正常」,会话同步每秒播一次已用秒数。
分发
Windows 安装包改走 GitHub。Gitee 单文件上限 100 MiB,windows-x64-setup.exe 已到 104.0 MB、余量不足 1 MB,再涨一次就会在发布阶段失败。Linux 与 macOS 包仍在 Gitee,GitHub 全平台都有。
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- 本版没有新增遥测。分析页只读本机 git 仓库,不发任何网络请求。
验证
- 类型检查、
vue-tsc、ESLint 与生产构建全部通过;124 个文件 / 1214 个用例全绿。 - 界面断言 338 项(真机跑):分段控件的选中态亮度与描边、热力图提示框的 6 种收起路径、仓库范围多选的筛选态计数。
- 0.1.47 期间补的测试基建一并生效:验收脚本吸收 CDP 崩溃与 WebSocket 断线、竞态用例改用握手开窗(满负载下不再假通过)、并发限到 4(git 子进程抢资源导致的假超时不再出现)。
- 变异验证(确认断言真的会拦):删掉切仓库时的忙态重置 → 两条结构性断言全挂;段控件退回弱底色 → 五套主题四个不达标;删掉内描边 → 五套全缺;按钮退回只写「全选」→ 精确挂掉两条;保存队列改回按快照比较 → 主题往返用例失败。
- 量过的时序:连续勾选 525 → 107 ms,块操作空窗 215 → ~60 ms,冲突解决忙态 156 → 114 ms。
Moo Fleet 0.1.46
本次更新
这一版的主体是一个新页面:跨仓库提交分析。前面几十个版本解决的都是「这个仓库现在什么状态」,这一版回答的是另一个问题——我到底在什么时间、写了多少、写在哪。数据全部来自本机已有的 git 仓库,不上传任何东西,也不要求额外配置。
从 0.1.36 到这一版,一共 24 个提交、77 个文件、约 1.25 万行新增;除了分析页,设置面板与工作区摘要也重做了一遍。
一、提交分析:把「写了什么」变成「什么时候写的」
分析页放在顶栏第三个入口。整页共用一个时间窗口,切换范围时所有卡片一起变,不会出现热力图看一年、构成条看全历史这种混口径。
- 提交热力图:日 × 周的网格,四档窗口(近 3 个月 / 近 6 个月 / 近一年 / 近两年)。格子的深浅按窗口内单日最大值分四档,不是绝对值——否则淡季整张图会全灰。窗口左侧边缘不足两周的残月不再抢占刻度位,月份标签是连续的。
- 提交时段:7 × 24 的星期 × 小时矩阵,按提交者本地时间统计。「凌晨三点在写代码」比「UTC 19:00」有用,所以不做时区归一化。
- 非上班时间:工作时段定为 08:30–12:00 与 13:30–18:00,其余(含午休)与周末全天计入。大数字是小时数,副行给折合多少个 8 小时工作日,下方三段构成条拆清晨 / 晚间 / 周末。
- 代码量:
--numstat逐文件统计增删行,剔除锁文件、.min.js、.map、node_modules与dist/build/coverage等产物目录,以及带「自动生成」标记的文件。合并提交不计。 - 仓库活跃度:按「最近一次提交距今」分 7 天内 / 8–30 天 / 31–90 天 / 91 天以上四档,并单列「从未提交」的数量。
- 排行:仓库与作者各一张,可在「提交数 / 增删行」之间切换。
- 作者归并:同一个人的不同写法会合成一条——同邮箱、姓名 token 完全相同、或短名是长名的前缀且不短于 4 个字符,三种关系取并集。显示名取出现最多的写法,其余进别名。
二、口径只有一个出处
时间窗口、工作时段、聚类阈值这些数字,全站只在一处定义(src/shared/report-window.ts 与 src/shared/work-window.ts),服务端算数、客户端写文案都引它。这不是洁癖:早先「近一年」的副标题写着「过去 52 周」,里面装的却是全历史总数,和紧挨着的卡片差 22%,就是因为两个地方各算各的。
扫描范围用的是 --branches --remotes --tags HEAD,而不是 --all——后者会把 refs/stash 与 refs/notes 也算进来,等于把草稿和笔记当成提交历史。
三、快,是因为只算该算的部分
第一版每次刷新都把全部仓库的提交重新扫一遍。现在:
- 提交历史按仓库缓存,切换时间范围只在内存里按日期过滤,不重跑
git log; - 代码量走增量:只对窗口内新增的提交补
--numstat,旧条目原样保留,窗口收窄时也不裁剪基线; - 页面每 60 秒轮询一次,同一请求并发时复用同一次扫描。
--shortstat 被否掉了:它看起来只是一次调用,实测耗时是 --numstat 的 24 倍(0.01 s → 0.24 s),放进轮询里等于持续占着 CPU。
四、可以只看一部分仓库
工具栏右侧是可搜索的仓库多选:输入关键字按「名称 / 分组 / 路径」过滤,支持全选与清空,选择结果记在本机。清空后是「一个都没选」,不是回退成全选——想看某个仓库时不必先反选 52 个。整页聚合、排行、构成条都跟着范围走。
五、这一版还顺手改了
- 设置面板重做:分组、层级与间距重新排过,选项不再挤成一列。
- 工作区摘要按语义着色:待推送、待拉取、有改动不再共用一个颜色,扫一眼能分清哪个是「要处理」、哪个只是「有变化」。
- 后端不再留孤儿进程:应用被强制结束或崩溃时,本地服务会自己退出,不再占着端口让下次启动挑到别的端口。
- 构建中间目录改成挪走:
dist/release/macos-*这类目录不再就地删除,先改名挪到release/.stale-*,避免一次删几十个文件把构建卡在中途。 - 工程:接入 ESLint 并清零 12 个依赖漏洞,UI 断言脚本入库(截图与验证共用同一份夹具)。
六、三回合审查修掉的问题
这一版在发布前做了三轮独立检查(业务代码 / 视觉 / 交互),修掉六处:
| 问题 | 表现 |
|---|---|
| 数字格式化进位越界 | 99,999,999 会显示成「10000 万」——没有这个单位 |
| 月份刻度固定丢一个月 | 近一年显示「10月 … 12月」,11 月凭空消失 |
| 超宽屏热力图不铺满 | 2304 宽下只占卡片 56%,右侧空出近一千像素 |
| 近两年横向滚动无提示 | 标题写着「近两年」,图却停在 8 月;现在溢出时停到最右端,延续的一侧渐隐 |
| 多选里「已选」反而更难读 | 勾中的仓库名被染成品牌绿,对比度 4.1:1,未选中的白名是 9.5:1 |
| 焦点环两种颜色 | 分段按钮用青柠绿,其余控件用品牌绿,同一页两种环 |
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- Windows 与 Linux 包未做代码签名,首次运行可能触发系统警告。
- 本版没有新增遥测。分析页只读本机 git 仓库,不发任何网络请求;唯一的对外请求仍是用户主动点击「检查更新」时读取一次公开的 releases 页面。
验证
- 类型检查、
vue-tsc、ESLint 与生产构建全部通过;119 个文件 / 1119 个用例全绿。 - 真机(53 个真实仓库,0 个读取失败):
sum(daily) = sum(hourly) = sum(byRepo) = sum(byAuthor) = 提交总数,三个时间范围逐项对得上;代码量在仓库维度与作者维度两侧求和相等;offHours = workday + weekend、early + lunch + evening = workday。 - 界面在 2304 / 1440 / 1354 / 1280 / 1024 五档宽度与五套主题下检查过,无横向溢出;键盘路径(打开选择器 → 搜索 → 上下移动 → 切换 → Esc 关闭并归还焦点)逐段实测。
- 失败与恢复:停掉本地服务后点刷新,3 次重试后出现「连不上 Moo Fleet 本地服务……下面仍是上一次成功统计的结果」,图表保留;服务恢复后点「重试」条幅消失。
Moo Fleet 0.1.36
本次更新
这一版集中在两处「每天都在看」的地方:顶栏太占地方,仓库详情页又太吵。顶栏从一排文字收成一排图标,多了 GitHub 入口与检查更新;详情页把重复的路径、常显的红色图标和三条描边都收了,并在空预览处补上真正可用的键位提示。
顶栏:先减字,再补入口
原来「操作记录」「刷新状态」各是一个带图标和文字的中等按钮,加上 LOCAL API 与 READY 两段常驻文字,右半边长期被这些状态占着。现在:
- 操作记录与刷新退回图标,36 px、与其它图标按钮同一套 hover/聚焦样式;正在跑的时候图标位置不变,只换颜色与角标,不会因为文字出现消失而把右侧整排推来推去。
LOCAL API/READY收成一个 7 px 圆点:有它、没它、异常三种状态仍然可分,靠颜色和title说明,不再用两段大写单词占一格宽度。- 新增 GitHub 入口,直接指向仓库主页;旁边是检查更新。
- 窄窗口不再靠删改 CSS 层层叠,改成 900 / 520 / 420 px 三档:先收副标,再收快捷键提示与 GitHub,最后缩 logo。四档实测横向溢出都是 0。
检查更新:判断的是上游 tag,不是文案
点击才查,不跟页面轮询走。判断依据是 GitHub releases/latest 重定向到的那个 tag,与「发版记录里写了什么」无关——只比 MAJOR.MINOR.PATCH,v 前缀与 -beta 一类后缀不参与比较;解析不出来时按「没有新版本」处理,宁可不说有新版本。
这里踩了一个坑并绕开:api.github.com 匿名按 IP 限流 60 次/小时,本机实测第一次就 403。改成读 https://github.com/<owner>/<repo>/releases/latest 的 302 location——不认证、不占配额,请求带 redirect: 'manual',否则跟到 tag 页面就只剩 HTML。
失败不弹全局 toast:拿不到更新只是少一条提示,不该像操作失败那样打断人。查询成功后结果在进程内缓存 5 分钟,失败不缓存、只写中文原因(超时 / 连不上 / 被限流 / 上游还没有发布记录),面板里如实显示原因而不是「已是最新」——否则断网会被说成没有新版本。
版本号仍然只有一个来源:package.json,由 vite.config.ts 的 define 内联成 __APP_VERSION__,界面与检查逻辑共用它。
仓库详情页:去掉重复,把破坏性动作收起来
- 同目录不再一行写一遍。平铺清单里连续同目录的文件只标一次路径,目录一变(或中间夹了根目录文件)才重新标;树形视图的目录行已经交代了层级,文件行不再写第二遍,行高从 40 px 收到 32 px,与目录行同高,滚起来不再一大一小交替。
- 行尾的丢弃 / 删除默认不显示。16 行清单里常显就是一列红图标,像在催人点。现在 hover、键盘聚焦或当前正在预览的那一行才显形;位置一直预留,显隐不会让文件名跳动。触屏设备(
hover: none)保持常显。 - 「平铺 / 已标记 / 已忽略」三条去掉常显描边。三个同样粗细的框并排,会读成三个同等重要的动作;现在只有激活态才有底色和边框。「已标记」的图标从
EyeOff换成书签——「眼睛划掉」更像隐藏而不是标记。 - 工作区副行只留分支名。文件数量在「变化文件 N」和「已勾选 x / y」里各出现一次,第三遍只是稀释标题。
- 提交卡:没选文件时不再显示「0 个文件」;禁用态的提交按钮从整宽品牌绿实心块改成透明描边——它比「提交」这个动作本身还抢眼;
⌘/Ctrl ↵提示只在真能提交时出现。 - 空预览的快捷键提示,以及一个被真机抓出来的问题:上一版这里写着「↑↓ 选择文件」,但焦点停在空白处时按键没有任何反应——原来的处理只认「焦点已经在文件按钮上」的事件,而焦点在页面根部时按键事件根本到不了文件列表。现在改成窗口级接管:焦点不在任何控件或其它浮层里时,↓ 从当前项往下、↑ 往上,没有选中时分别落到第一个和最后一个;焦点在按钮、输入框、分支列表或提交历史视图时一律让行,不抢别人已经定义好的上下键。
- 顺带:Pull / Push 的
0徽标为 0 时不再渲染;顶栏「刷新」前加一条 1 px 竖线,与走网络的 Fetch / Pull / Push 分开。
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- Windows 与 Linux 包未做代码签名,首次运行可能触发系统警告。
- 本版没有新增遥测;唯一的对外请求是用户主动点击「检查更新」时读取一次公开的 releases 页面。
验证
- 类型检查、106 文件 / 904 用例、生产构建全部通过。
- 真机复核(真实 Chrome + 真实 git 仓库,含重命名、部分暂存、根目录文件与深路径):平铺目录去重、树形视图行高一致、行尾图标 hover 显形且不抖动、三条开关只有激活态有描边、空预览键位可用,均已实测;焦点在顶栏按钮 / 分支列表 / 提交历史视图时按上下键都不被劫持。
- 布局在 1440 / 1280 / 1024 三档无横向溢出;900 视口下详情页右侧被裁属于既有的 1024 px 最小宽度约束,不是本版引入。
Moo Fleet 0.1.35
本次更新
这一版几乎全是「出问题时」的体验:仓库目录被挪走时不再甩一句 errno,克隆远端时少绕几步,冲突暂停后界面不再停在操作之前的样子,大改动不再显示一个算错的增删数。桌面版另外修掉了启动那一下的闪白与闪灰。
仓库不可用时,说清楚发生了什么
仓库目录被移动或删除后,刷新提示的是 ENOENT: no such file or directory, realpath '/private/var/…'——既有内部路径,也没说该做什么。现在改成「仓库目录不存在:<路径>。它可能已被移动或删除,请重新接入。」
目录还在、.git 被删掉时透出的 git 英文 fatal 也一并改写;只按 stderr 内容识别这一种,超时等其它失败原样抛出,避免把「git 卡住」误报成「不是仓库」。
更要紧的是第二个问题:打开这类仓库时,文件列表只按「空数组」判断,于是显示「工作区干净 · 所有改动均已提交」——读不到被当成了没有改动。现在列表为空且读取失败时显示错误空态和「刷新后重试」;已有内容时保留旧内容只弹提示,不把画面整个换成错误页。
克隆远端:少绕几步
- 地址可以直接粘。输入框右侧多了粘贴按钮,能处理从网页、终端、Markdown 表格里抄来的各种形态:成对的引号/反引号/尖括号(可以套两三层),以及整条
git clone --depth 1 …命令——从中取出地址,选项和它们的取值不会被误认。粘贴、提交、服务端执行共用同一份规范化。 - 位置撞车在提交前就拦住。目标目录已经有仓库时,字段上方直接说明「这个位置已经有仓库「x」了,请换一个目录名」,不再让你先确认、等一次克隆、再看到报错。只认目录确实还在的仓库:登记了但目录已丢失的,克隆正好能把它补回来。
- 目录名校验与服务端同一套。
..、以-开头、含路径分隔符、含控制字符,各给各的理由,按钮同时变灰。 - 克隆中锁住输入。根目录与两个输入框在克隆期间禁用并有明显的禁用样式——这时改地址不会影响已经在跑的那次克隆,只会让人以为改的是它。副按钮从「取消」改成「关闭」:git 已经在跑,这个按钮取消不了任何事,如实写成关闭。底部显示已经过去的秒数。
- 失败先给一句人话,原始 stderr 留在下面一行供排查;常见情况(仓库不存在、网络不通)会概括成一句能照着做的提示。
- 成功后直接打开新仓库。之前克隆完要自己去列表里找;现在抽屉自动展开,键盘焦点落在里面(这里还修了一个焦点陷阱:正在淡出的弹窗仍被当成「最上层」,焦点被送进即将被移除的输入框,元素一移除就掉到页面根部)。提示也改到抽屉打开之后设置,否则会闪一下就被抽屉挤掉。
写操作与大改动
- 冲突暂停后不再是旧画面。merge / rebase / revert / cherry-pick 停下来时重新取一次状态并切到工作区,能看到冲突,也能看到「继续 / 终止」。
- 「进行中的操作」升为常驻提示位,且优先于 detached 判断——rebase 期间 HEAD 天然游离,那时该继续或终止,而不是新建分支。
- 没有远端的仓库,Fetch 不再可点;批量操作遇到这类仓库按「跳过」处理,不再算成失败,让「需处理」能归零。
- 差异截断不再算错增删。改动超过 120 KB 时只显示前 120 KB,并且不再拿截断后的补丁去算增删统计(1 万行改动曾显示成
+0 −1654)。顶部常驻一句「仅显示前 120 KB」;按块暂存入口改用结构化字段判断,不再嗅探补丁尾部的字符串。 - 二进制差异单独呈现,不再把补丁头当正文渲染。
- 标签可以探测远端是否已存在;批量条去掉「已选 1 1」这种重复计数;焦点样式统一为蓝。
桌面版(macOS)
- 启动不再闪白,也不再闪灰。首帧之前那块底色由系统决定,
WKWebView.underPageBackgroundColor管不到(把它临时改成纯红启动,红色一次都没出现),改为在网页上盖一层画布色视图,页面加载完成后淡出;加载失败与 8 秒兜底都会撤掉它,不会停在纯色上。 - 窗口标题栏那条带与页面画布统一用 sRGB 取色,不再偏色。
- 1024 宽下仓库行的版本号不再被截成
v0.1.…;克隆弹窗的地址占位、「未设置 upstream」也不再截断(后者补了悬停提示)。
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- Windows 与 Linux 包未做代码签名,首次运行可能触发系统警告。
- 本版没有新增遥测或网络请求;凭证只在本机钥匙串与 git 之间流转。
验证
- 类型检查、104 文件 / 889 用例、生产构建全部通过。
- 克隆链路在隔离实例里实跑:粘贴带引号的
git clone --depth 1 "git@gitee.com:…"得到干净地址;../-rf/a/b三种非法目录名各给不同理由且按钮禁用;已存在的目标位置在确认弹窗之前就被拦下;成功克隆后抽屉自动打开、焦点在内部、内联提示约 4 秒后消失且没有 toast 闪现。 - 真机(装进
/Applications的构建)验收:启动帧序列从白色 → 系统灰(30,30,30)变为画布色(13,19,30);1024 / 1180 / 1440 / 1920 四档宽度无横向溢出。 - 六个产物逐个核对:字节数与 sha256 见
SHA256SUMS-0.1.35.txt。macOS 两包 ad-hoc 签名通过codesign --verify --deep --strict,挂载后确认版本 0.1.35(build 135)、架构分别为 arm64 / x86_64、内测安装器随包分发;Windows 与 Linux 包未签名,载荷结构、版本、架构与体积经verify-desktop-packages.sh全部通过(Windows 安装包 99.4 MiB,距 Gitee 单文件上限还有 575 KiB)。
Moo Fleet 0.1.34
本次更新
这一版解决三件与「把一个项目接进来」有关的事:检出远端分支不再被一个过严的门槛挡住,加入新仓库不用再钻进设置里翻,私有仓库克隆失败时会当场问你要账号。
检出远端分支不再要求工作区干净
以前「检出」按钮经常是灰的,即使你只是多了几个未跟踪文件。原因不是渲染出错,而是客户端与服务端都硬性要求工作区完全干净,判据里连未跟踪文件都算。
这个门槛站不住:git switch --track --create 和切到已有本地分支是同一种操作——能兼容的本地改动与未跟踪文件会被一起带过去,只有会覆盖本地内容时才拒绝,而且拒绝时分支引用、HEAD 与工作区三者都不变。
现在交给 Git 判断:
- 有改动也能检出,兼容的改动随分支带过去;
- 会覆盖本地内容时 Git 拒绝,界面说明原因,本地内容完好;
- 未解决冲突、进行中操作、只读、Worktree 占用、远端引用漂移这些护栏一个都没放宽;
- 「创建并切换」仍然要求干净工作区,但确认弹窗里可以取消勾选,只创建分支引用。
首页就能加入仓库
此前仓库舰队首页没有任何「加入仓库」入口——正常路径是头像 → 设置 → 「仓库接入」→ 滚过配置目录与扫描,才轮到克隆。克隆是加入新项目最深的一步,而它本身只是一个自包含表单。
- 批量操作那一行的右端常驻「添加仓库」与「克隆远端」,与列表同屏可见;
- 两者都是偶尔用一次的动作,所以默认无边框、无底色、用弱化文字色,只在悬停或键盘聚焦时显形;
- 克隆改成独立弹窗:选根目录、填地址、按回车即可,成功后收起并提示,失败时错误留在弹窗里;
- 设置里的「03 克隆远端仓库」已删除,克隆只有这一个入口,扫描列表下方留了一句指向。
顺带修掉两处真实缺陷:只有一个扫描目录时,表单仍停在「请选择要克隆到哪个目录」(rootId 从来没有默认值);关闭弹层后键盘焦点落到页面根部,要重新 Tab 一整圈才能回到触发按钮。
克隆私有仓库失败时,当场补填凭证
GIT_TERMINAL_PROMPT=0 之下,缺凭证的克隆只会得到一句 could not read Username,以前这句话就那样躺在弹窗底部,得自己猜到是认证问题、再去设置里找凭证入口。
现在按失败类型给下一步,而不是每次克隆都先问一遍账号:
| 失败类型 | 界面反应 |
|---|---|
| 该主机还没有凭证 | 就地展开「用户名 + 访问令牌」,主机预填、焦点直接落在用户名;保存进系统钥匙串后自动重试一次 |
| 已保存的凭证被拒绝 | 同一表单,提示可能已过期,用户名保留、令牌框清空 |
| SSH 主机指纹未信任 / 公钥被拒 / 主机名解析失败 | 只给准确指引(如 ssh -T git@主机),不摆一个填了也没用的表单 |
| 未加密的 http 地址 | 提示改用 https——凭证按 protocol=https 存取,填了也命中不了 |
- 凭证存在系统钥匙串,Moo Fleet 不保存副本,也不写进仓库配置;
- 地址一改,补填面板就收起、上一次的失败信息一并清掉,避免把令牌存到另一个主机;
- 面板展开时底部只留「取消」,「保存并重试」成为主按钮,不会再让你重复撞同一堵墙。
修复
- 克隆失败的错误行不再带 git 的进度前缀(
Cloning into 'x'...)与fatal:,只留原因。 - 禁用按钮上挂
title是无效的(禁用控件不派发鼠标事件,弹不出 tooltip),改为内联说明。
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- Windows 与 Linux 包未做代码签名,首次运行可能触发系统警告。
- 本版没有新增遥测或网络请求;凭证只在本机钥匙串与 git 之间流转。
验证
- 类型检查、104 文件 / 880 用例、生产构建全部通过;新增
clone-auth.test.ts14 项,branches.test.ts换成两条真实 Git 用例(兼容改动随分支带走、冲突时拒绝且仓库三者不动)。 - 检出放宽在临时 bare 仓上逐场景实测:未跟踪文件与兼容改动都带过去、upstream 正确建立;远端与本地对同一文件各有版本时拒绝,仍在原分支、未创建新分支、本地内容完好。
- 克隆补填跑的是出厂产物:用已安装包自带的 Node 与 server bundle 起隔离实例,对端是一个要求 Basic 认证的真 HTTPS Git 服务。首次克隆展开面板并聚焦用户名 → 填错令牌转「凭证被拒」→ 改对令牌后不弹二次确认、克隆成功、仓库入列,钥匙串与
origin/main跟踪都核对过。 - 四个桌面包的载荷结构、版本、架构与体积全部通过校验;macOS 两包为 ad-hoc 签名,Windows/Linux 未签名。
Moo Fleet 0.1.33
本次更新
这一版没有功能改动。改的是「怎么保证以后不悄悄坏掉」——补了三道检查、修了两个读不清的颜色。
两个读不清的颜色
Monokai 主题里有两处文字对比度低于 WCAG AA(4.5:1):
| 用途 | 原值 | 新值 | 对比度 |
|---|---|---|---|
| 语法关键字、标签 | #F92672 |
#FA4E8C |
3.93 → 4.62 |
| 错误 / 冲突 / 删除 | #F44747 |
#F55C5C |
4.13 → 4.65 |
只提了明度,色相和饱和度没动,观感仍是 Monokai。红色这次也一并调了——它和关键字色落在同一个阅读区底色 #272822 上,此前只有它被记录过,关键字色从来没测过。
其余四套主题的非注释色本来就都过 4.5。
主题配色现在有测试兜底
五套主题各 40 个颜色变量,靠 CSS 自定义属性继承生效:少写一个不会报错,只会静默拿到上一套的值,表现成「切到某个主题后有一处颜色不对」,肉眼极难定位。
现在有 117 个用例守着:五套的变量集合必须与清单完全一致(缺哪个、多哪个分别列出)、同一套内不能重复声明、21 组前景/背景的对比度不低于下限。阈值按语义分档——正文、状态色、语法色 4.5,注释 3.0(五套实测 3.40–3.95,按 4.5 会把所有主题的注释都逼成正文色)。
桌面包现在真的会被拆开验
以前 CI 只看「四个安装包存在、都小于 100 MiB」,载荷里是什么没人验。现在每次构建后用 7-Zip 直接读 NSIS 与 SquashFS 容器,核对 44 项:主程序与 resources/app/dist/{client,server} 在不在、app.asar 有没有被打开(必须保持关闭,否则 ELECTRON_RUN_AS_NODE 子进程读不到服务端入口)、deb 的版本架构与 .desktop 的 Exec/Icon/StartupWMClass、Windows 主程序是不是 x86-64 PE、载荷内版本号是否与发布版本一致。
发布校验
新增 npm run release:checksum / release:verify:生成 SHA256SUMS,逐件核对哈希并报告平台签名状态(macOS 读 codesign 主体、Windows 读 PE 证书表、deb 查 _gpgorigin)。产物清单改由 release/Moo-Fleet-<版本>-artifacts.json 驱动,加新 target 不用同时改脚本和 CI。
说明
- macOS 包为 ad-hoc 签名的内测包,未经公证;请用 DMG 内的「安装 Moo Fleet(内测)」,不要手动拖进「应用程序」(下载隔离属性会导致应用无法启动)。Apple Silicon 与 Intel 请选对应架构的 DMG。
- Windows 与 Linux 包未做代码签名,首次运行可能触发系统警告。
- 界面行为、接口、数据结构与 0.1.32 完全一致,升级不会改任何仓库文件或配置。
验证
vue-tsc/tsc类型检查通过。- 103 文件 / 864 用例通过(0.1.32 是 102 / 747)。
npm run verify:desktop44 项全过;用不存在的版本跑负例会正确退出 1。npm run release:verify六件哈希全部 ok。npm run docs:palettes通过,配色文档与styles.css逐 token 一致。