返回 DeepSeek-Reasonix
upgrade_backup.go
根目录 / desktop / internal / draftstate / upgrade_backup.go
1 package draftstate
2
3 import (
4 "database/sql"
5 "fmt"
6 "os"
7 "path/filepath"
8 )
9
10 // VACUUM INTO reads a consistent SQLite snapshot including committed WAL
11 // frames. Copying only the main database would lose acknowledged input.
12 func backupBeforeUpgrade(db *sql.DB, path string, version int) error {
13 backup := fmt.Sprintf("%s.pre-v%d.sqlite", path, SchemaVersion)
14 if _, err := os.Stat(backup); err == nil {
15 return nil
16 } else if !os.IsNotExist(err) {
17 return err
18 }
19 file, err := os.CreateTemp(filepath.Dir(path), ".draft-upgrade-*.sqlite")
20 if err != nil {
21 return err
22 }
23 temporary := file.Name()
24 if err := file.Close(); err != nil {
25 return err
26 }
27 defer os.Remove(temporary)
28 if _, err := db.Exec(`VACUUM INTO ?`, temporary); err != nil {
29 return fmt.Errorf("backup draft schema %d: %w", version, err)
30 }
31 if err := os.Chmod(temporary, 0600); err != nil {
32 return err
33 }
34 // Link publishes without replacing a snapshot another upgrader produced.
35 if err := os.Link(temporary, backup); err != nil && !os.IsExist(err) {
36 return err
37 }
38 return nil
39 }
40
40 lines GO