跳转到主内容

哪个笨蛋写了这段代码?

· 1 分钟阅读
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

终究还是发生了:我引入了一个bug,该问题仅出现在特定场景中——当用户同时使用新旧版本Oh My Posh时会出现且无法修复。你可能会问:谁会这么用?常见场景包括在Windows上使用WSL,或在任何系统中使用虚拟机时跨安装共享同一份配置。这虽非主流使用场景,但也并不罕见。

发生了什么?

今年年初,经过一番苦战,我终于完成了自Go语言重构以来最重要的架构更新。为此需要进行旧配置迁移,避免用户手动调整配置映射——这种逻辑处理显然交给计算机更合适。

为此我在配置中添加了version属性,当配置演进时可递增版本号,并在必要时触发自动迁移。迁移需求的判断逻辑如下:

if !env.Flags().Migrate && cfg.Version != configVersion {
cfg.BackupAndMigrate(env)
}

眼尖的读者现在应该能发现问题所在了。对于习惯阅读而非思考的我们来说,结果显而易见:迁移总会执行——要么强制触发(通过手动执行oh-my-posh config migrate),要么当前配置版本与需求版本不匹配时自动触发。很简单对吧? 在更新Oh My Posh时这套逻辑完全符合预期。但当你在同一台机器上使用多个版本并共享配置时,问题就出现了。

想象这样的场景:你在多个终端环境工作,WSL Ubuntu里的Oh My Posh停留在版本1(S1)。某天你在Windows PowerShell更新到了最新版,即版本2(S2)。启动S2时,它会自动将配置迁移到版本2,把template属性转移到segment模型里。

具体来说,下面这个版本1配置:

{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 1,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"background": "#9A348E",
"foreground": "#ffffff",
"leading_diamond": "\ue0b6",
"properties": {
"template": "{{ .UserName }} "
},
"style": "diamond",
"type": "session"
}
]
}
]
}

会被迁移为:

{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 2,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"background": "#9A348E",
"foreground": "#ffffff",
"leading_diamond": "\ue0b6",
"template": "{{ .UserName }} ",
"style": "diamond",
"type": "session"
}
]
}
]
}

表面上一切完美:零用户干预且_完全按设计运行_。但当你试图在S1环境中操作时,根据逻辑设定,Oh My Posh检测到2 != 1便会触发版本1的迁移流程。迁移本身不会中断运行,但此时Oh My Posh无法识别segment中的template属性。最终导致配置结果异常恼人,如下所示:

{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 1,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"background": "#9A348E",
"foreground": "#ffffff",
"leading_diamond": "\ue0b6",
"style": "diamond",
"type": "session"
}
]
}
]
}

😱 模板消失了!不过别慌,Oh My Posh会使用默认模板,所以提示符仍能显示。迁移过程还会_自动备份_之前正确的版本2配置。此时你仍可回滚,虽然很糟心,但本地修改还在。但如果你继续使用S2环境,它会再次触发版本2迁移,用有问题的版本1配置覆盖你的备份

虽然代码修复很简单,但无法推送到旧版本。用户通常会升级到最新版,在这种特定环境下可能导致故障。建议一次性升级所有环境版本,确保只迁移一次,避免残留旧版本触发这个副作用。

具体修复方案参见7.52.1版本,但显然该方案仅适用于从版本2升级到未来新版本的场景。

if !env.Flags().Migrate && cfg.Version < configVersion {
cfg.BackupAndMigrate(env)
}

虽然我在验证逻辑时已竭尽全力考虑所有可能的边缘情况,但总有疏漏发生。即使现在回顾这个案例,我也很难理解当初为何会忽视这种情况,但它确实发生了。不过好消息是:同样的问题绝不会再出现 😅