Skip to content

Commit 64a0c6e

Browse files
committed
fix bckp behavior
1 parent a762709 commit 64a0c6e

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

backup.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"net/url"
67
"os"
@@ -125,7 +126,38 @@ func (bm *BackupManager) ensureRepo(remoteURL string) error {
125126
return nil
126127
}
127128

129+
// snapshotTransactionCount parses a JSON backup string and returns the number
130+
// of transactions it contains. Returns 0 on any parse error (treats corrupt/empty
131+
// JSON as having no transactions).
132+
func snapshotTransactionCount(jsonData string) int {
133+
var s struct {
134+
Transactions []json.RawMessage `json:"transactions"`
135+
}
136+
if err := json.Unmarshal([]byte(jsonData), &s); err != nil {
137+
return 0
138+
}
139+
return len(s.Transactions)
140+
}
141+
142+
// fetchRemoteJSON fetches the remote backup file content without modifying the
143+
// working tree. Returns "" if the remote does not exist yet or has no backup
144+
// file — that is not an error, it just means this is the first push.
145+
func (bm *BackupManager) fetchRemoteJSON() string {
146+
// Update remote refs. Ignore errors (remote may not exist yet).
147+
bm.runGit("fetch", "origin") //nolint:errcheck
148+
out, err := bm.runGit("show", "FETCH_HEAD:self_ledger_backup.json")
149+
if err != nil {
150+
return ""
151+
}
152+
return out
153+
}
154+
128155
// BackupNow writes jsonData to the local repo and pushes to the remote.
156+
// It skips the commit/push when:
157+
// - the remote already contains identical content (no-op), OR
158+
// - local has no transactions but remote does — this prevents an empty-DB
159+
// force-push from overwriting real data when the app first launches on a
160+
// new device before the user has restored from backup.
129161
func (bm *BackupManager) BackupNow(jsonData string) error {
130162
cfg, err := bm.LoadConfig()
131163
if err != nil {
@@ -144,6 +176,18 @@ func (bm *BackupManager) BackupNow(jsonData string) error {
144176
return err
145177
}
146178

179+
// Fetch remote content and compare before writing anything.
180+
remoteJSON := bm.fetchRemoteJSON()
181+
if remoteJSON == jsonData {
182+
// Remote is already up to date.
183+
return nil
184+
}
185+
if snapshotTransactionCount(jsonData) == 0 && snapshotTransactionCount(remoteJSON) > 0 {
186+
// Local DB is empty but remote has data. Skip to avoid overwriting a
187+
// real backup with a blank slate (typical on first launch of a new device).
188+
return nil
189+
}
190+
147191
backupFile := filepath.Join(bm.repoPath, "self_ledger_backup.json")
148192
if err := os.WriteFile(backupFile, []byte(jsonData), 0600); err != nil {
149193
return err

0 commit comments

Comments
 (0)