fix: 数据目录移出安装目录,修掉「覆盖安装/卸载即丢数据」
根因:数据目录是 <安装目录>\data(config.yaml 的 dataDir 相对服务端工作目录),
而 electron-builder 的卸载器结尾执行 RMDir /r $INSTDIR,且覆盖安装会先跑旧卸载器
(installSection.nsh:52 的 uninstallOldVersion)→ 赛事库/规则/用户/审计/上传图片
连同安装目录被整个删除,再装新版。卸载一次同样如此。
- 服务端新增 -data <dir>(主命令、backup、passwd 三处),非空时覆盖 config.yaml 的
dataDir;不传时行为完全不变(兼容便携/手工运行)
- Console 把数据指到当前用户目录 %LOCALAPPDATA%\ScoreboardConsole\data(卸载器不会碰
这里;没有用 app.getPath('userData'),因为 %APPDATA%\<AppName> 正是被删的那个)
- 一次性迁移:目标为空且 <安装目录>\data 有数据时整体改名过去;两边都有数据时不动作
只记警告;任何失败都保留原地数据、绝不删除
- passwd 也带 -data(否则重置的是安装目录下那个空库里的账号)
- deploy/backup.bat 指向同一数据目录
- 文档:部署指南新增「数据放在哪里(升级/卸载都不会删)」+ 备份/恢复/迁移路径改写,
上线检查清单与使用手册同步
自检:服务端 12 包全绿;console 语法 14 文件 + datadir 单测 11/11;backup.bat 保持纯 ASCII。
This commit is contained in:
1 parent
6483acf9ad
commit
005b51b2ec
18 files changed
+626
-64
No files matched your search
@@ -71,6 +71,17 @@ func Load(path string) (*Config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// ApplyDataDir 用命令行显式指定的数据目录覆盖配置里的 dataDir:dir 为空或只有空白时保持原样。
|
||||
// 返回是否发生了覆盖,调用方据此记录数据目录来源。
|
||||
func (c *Config) ApplyDataDir(dir string) bool {
|
||||
dir = strings.TrimSpace(dir)
|
||||
if dir == "" {
|
||||
return false
|
||||
}
|
||||
c.DataDir = dir
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Config) validate() error {
|
||||
if c.Server.Port <= 0 || c.Server.Port > 65535 {
|
||||
return fmt.Errorf("server.port 非法: %d", c.Server.Port)
|
||||
|
||||
@@ -29,3 +29,37 @@ func TestLoadAllowedOrigins(t *testing.T) {
|
||||
t.Fatalf("白名单解析错误: got %v want %v", cfg.Server.AllowedOrigins, want)
|
||||
}
|
||||
}
|
||||
|
||||
// -data 只在非空时覆盖配置:不传与传空串都必须保持配置文件里的值,
|
||||
// 否则 Console 之外的便携/手工运行会被改写数据目录。
|
||||
func TestApplyDataDir(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
dir string
|
||||
want string
|
||||
applied bool
|
||||
}{
|
||||
{"非空覆盖配置值", `/var/lib/scoreboard`, `/var/lib/scoreboard`, true},
|
||||
{"两侧空白会被去掉", " /var/lib/scoreboard ", `/var/lib/scoreboard`, true},
|
||||
{"空串保持配置值", "", "cfg-data", false},
|
||||
{"纯空白等于不传", " ", "cfg-data", false},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "config.yaml")
|
||||
if err := os.WriteFile(path, []byte("dataDir: cfg-data\nserver:\n port: 19540\n"), 0o644); err != nil {
|
||||
t.Fatalf("写入配置: %v", err)
|
||||
}
|
||||
cfg, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("加载配置: %v", err)
|
||||
}
|
||||
if got := cfg.ApplyDataDir(tc.dir); got != tc.applied {
|
||||
t.Fatalf("ApplyDataDir(%q) 覆盖标记: got %v want %v", tc.dir, got, tc.applied)
|
||||
}
|
||||
if cfg.DataDir != tc.want {
|
||||
t.Fatalf("ApplyDataDir(%q) 后 DataDir: got %q want %q", tc.dir, cfg.DataDir, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user