diff options
Diffstat (limited to 'internal/game/cmd_swapid.go')
| -rw-r--r-- | internal/game/cmd_swapid.go | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/internal/game/cmd_swapid.go b/internal/game/cmd_swapid.go index bbcc79c..ef862b9 100644 --- a/internal/game/cmd_swapid.go +++ b/internal/game/cmd_swapid.go @@ -76,26 +76,35 @@ func (g *Game) executeSwapID(sess *net.Session, args []string, rawInput string) } } - // Swap the two files first. After this, path1 holds the old room id2's - // content and path2 holds the old room id1's content. Rebuilding the index - // then makes LoadRoom(id1)/LoadRoom(id2) return the swapped content, so the - // reference rewrite below operates on the correctly-positioned rooms and - // re-marshaling writes an `id:` field matching the new filename (keeping - // the file's id field consistent with its name, as the old regex did). - tempPath := path1 + ".swapid-tmp" - if rerr := os.Rename(path1, tempPath); rerr != nil { - sess.WriteLine(fmt.Sprintf("Error renaming room %d: %v", id1, rerr)) + // Swap the two files' contents first. After this, path1 holds the old room + // id2's content and path2 holds the old room id1's content. Rebuilding the + // index then makes LoadRoom(id1)/LoadRoom(id2) return the swapped content, + // so the reference rewrite below operates on the correctly-positioned rooms + // and re-marshaling writes an `id:` field matching the new filename. The + // swap runs as one journal transaction (like handleRoomRename/the account + // lifecycle), so a crash mid-swap is rolled back at the next startup + // instead of leaving both rooms at wrong paths with no recovery record. + data1, rerr := os.ReadFile(path1) + if rerr != nil { + sess.WriteLine(fmt.Sprintf("Error reading room %d: %v", id1, rerr)) return } - if rerr := os.Rename(path2, path1); rerr != nil { - os.Rename(tempPath, path1) - sess.WriteLine(fmt.Sprintf("Error renaming room %d: %v", id2, rerr)) + data2, rerr := os.ReadFile(path2) + if rerr != nil { + sess.WriteLine(fmt.Sprintf("Error reading room %d: %v", id2, rerr)) return } - if rerr := os.Rename(tempPath, path2); rerr != nil { - os.Rename(path2, path1) - os.Rename(tempPath, path1) - sess.WriteLine(fmt.Sprintf("Error finishing rename: %v", rerr)) + txn := g.newTxn() + if rerr := txn.Replace(path1, data2, 0644); rerr != nil { + sess.WriteLine(fmt.Sprintf("Error swapping rooms: %v", rerr)) + return + } + if rerr := txn.Replace(path2, data1, 0644); rerr != nil { + sess.WriteLine(fmt.Sprintf("Error swapping rooms: %v", rerr)) + return + } + if rerr := txn.Commit(); rerr != nil { + sess.WriteLine(fmt.Sprintf("Error swapping rooms: %v", rerr)) return } |
