From 8fe9e3c3fef0049df82281a62afe35dda516dfe2 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 17:48:26 -0400 Subject: fix: close combat ghost, admin traversal, login throttle, journal double-pay, and quality/economy gaps --- internal/admin/undo.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'internal/admin/undo.go') diff --git a/internal/admin/undo.go b/internal/admin/undo.go index 24ce9c1..c2ea61d 100644 --- a/internal/admin/undo.go +++ b/internal/admin/undo.go @@ -115,6 +115,47 @@ func (us *UndoStack) SetPlayerFileOnlineCheck(fn func(relPath string) bool) { us.playerFileOnlineCheck = fn } +// RewritePaths re-prefixes every stored history path under oldPrefix so a +// directory rename does not leave stale absolute paths behind. Without this +// a later undo recreates the old directory and writes a duplicate file while +// the live file stays in the new directory. newPrefix may be empty to leave +// paths untouched. +func (us *UndoStack) RewritePaths(oldPrefix, newPrefix string) { + if oldPrefix == "" || newPrefix == "" || oldPrefix == newPrefix { + return + } + us.mu.Lock() + defer us.mu.Unlock() + sep := string(os.PathSeparator) + rewrite := func(p string) string { + if p == "" { + return p + } + if p == oldPrefix { + return newPrefix + } + if strings.HasPrefix(p, oldPrefix+sep) { + return filepath.Join(newPrefix, strings.TrimPrefix(p, oldPrefix+sep)) + } + return p + } + rewriteDesc := func(c *ChangeDesc) { + c.FilePath = rewrite(c.FilePath) + c.NewFilePath = rewrite(c.NewFilePath) + for i := range c.ExtraFiles { + c.ExtraFiles[i].FilePath = rewrite(c.ExtraFiles[i].FilePath) + c.ExtraFiles[i].NewFilePath = rewrite(c.ExtraFiles[i].NewFilePath) + } + } + for i := range us.history { + rewriteDesc(&us.history[i]) + } + for i := range us.redo { + rewriteDesc(&us.redo[i]) + } + us.save() +} + func (us *UndoStack) Push(desc ChangeDesc) { us.mu.Lock() defer us.mu.Unlock() -- cgit v1.2.3