diff --git a/README.md b/README.md index 8249371..a967d13 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ Linux: curl -fsSL https://git.denkena-consulting.com/f-denkena/rclone-dropbox-bisync/raw/branch/master/linux/install.sh | bash -First run is --dry-run --resync until: +Missing listings + RCLONE_TEST on both sides: dry-run --resync, then live +--resync (install/daemon, not after a failed normal run). --accept-resync +skips the dry-run. Partial listings (one .lst) abort instead of resync. - rclone-bisyncd --accept-resync - -enabled=true only after RCLONE_TEST exists on dropbox:. Looping daemon sleeps -15 min after each finished run (no overlapping 15-min tasks). +enabled=true after a successful first resync, or if dropbox: already has +RCLONE_TEST at install. Looping daemon sleeps 15 min after each run. diff --git a/cmd/rclone-bisyncd/main.go b/cmd/rclone-bisyncd/main.go index 1ec0f61..c7ee046 100644 --- a/cmd/rclone-bisyncd/main.go +++ b/cmd/rclone-bisyncd/main.go @@ -89,13 +89,43 @@ func escapePS(s string) string { return strings.ReplaceAll(s, "'", "''") } -func listingsExist(cfg Config) bool { +func listingFiles(cfg Config) (path1, path2 string) { base := filepath.Join(cfg.Workdir, cfg.SessionName) - _, e1 := os.Stat(base + ".path1.lst") - _, e2 := os.Stat(base + ".path2.lst") + return base + ".path1.lst", base + ".path2.lst" +} + +func listingsExist(cfg Config) bool { + p1, p2 := listingFiles(cfg) + _, e1 := os.Stat(p1) + _, e2 := os.Stat(p2) return e1 == nil && e2 == nil } +func listingsPartial(cfg Config) bool { + p1, p2 := listingFiles(cfg) + _, e1 := os.Stat(p1) + _, e2 := os.Stat(p2) + return (e1 == nil) != (e2 == nil) +} + +func setEnabled(v bool) { + p := configPath() + b, err := os.ReadFile(p) + if err != nil { + return + } + var m map[string]any + if json.Unmarshal(b, &m) != nil { + return + } + m["enabled"] = v + out, err := json.MarshalIndent(m, "", " ") + if err != nil { + return + } + _ = os.WriteFile(p, append(out, '\n'), 0600) +} + func remoteHasCheckFile(cfg Config) bool { cmd := exec.Command(cfg.Rclone, "lsf", cfg.Path2, "--include", cfg.CheckFilename) out, err := cmd.CombinedOutput() @@ -179,24 +209,26 @@ func runOnce(cfg Config, acceptResync bool) error { return fmt.Errorf("missing %s on %s", cfg.CheckFilename, cfg.Path2) } + if listingsPartial(cfg) { + return fmt.Errorf("incomplete listings in %s (one side missing) — not auto --resync; fix or delete both .lst files", cfg.Workdir) + } if !listingsExist(cfg) { - if acceptResync { - _ = os.WriteFile(acceptPath(cfg), []byte("ok\n"), 0600) - } - if _, err := os.Stat(acceptPath(cfg)); err != nil && !acceptResync { - notify("rclone-bisync dry-run resync", "No listings yet. Inspect output, then: rclone-bisyncd --accept-resync") + // First use only: never auto --resync after a failed normal run. + if !acceptResync { + notify("rclone-bisync", "No listings — dry-run --resync") if err := runRclone(cfg, "--dry-run", "--resync"); err != nil { notify("rclone-bisync dry-run failed", err.Error()) return err } - return nil } - notify("rclone-bisync", "Live --resync starting (one-shot)") + notify("rclone-bisync", "Live --resync (first listings)") if err := runRclone(cfg, "--resync"); err != nil { notify("rclone-bisync resync failed", err.Error()) return err } - notify("rclone-bisync", "Live resync finished") + _ = os.WriteFile(acceptPath(cfg), []byte("ok\n"), 0600) + setEnabled(true) + notify("rclone-bisync", "Resync finished; enabled=true") return nil } diff --git a/linux/install.sh b/linux/install.sh index f508539..bdfe481 100755 --- a/linux/install.sh +++ b/linux/install.sh @@ -97,5 +97,5 @@ esac echo "Configured path1=$DROPBOX workdir=$WORKDIR (~/DataStorage)" echo "Startup: looping systemd --user service (sleeps 15 min after each run)" -echo "If listings are empty: dry-run --resync only. Then: rclone-bisyncd --accept-resync" +echo "No listings + RCLONE_TEST on both sides → dry-run --resync then live --resync" echo "enabled=$ENABLED (true only if dropbox: already has RCLONE_TEST)" diff --git a/linux/session-start.sh b/linux/session-start.sh index 5180c01..b0da156 100755 --- a/linux/session-start.sh +++ b/linux/session-start.sh @@ -3,5 +3,5 @@ set -eu systemctl --user daemon-reload 2>/dev/null || true systemctl --user enable --now rclone-bisync.service 2>/dev/null || true if command -v notify-send >/dev/null 2>&1; then - notify-send -a rclone-bisync "rclone-bisync" "Looping bisync started. First run is dry-run --resync until rclone-bisyncd --accept-resync." + notify-send -a rclone-bisync "rclone-bisync" "Looping bisync started. First use: dry-run then live --resync if both RCLONE_TEST exist." fi diff --git a/windows/Install.ps1 b/windows/Install.ps1 index ba75688..25aa1f7 100644 --- a/windows/Install.ps1 +++ b/windows/Install.ps1 @@ -37,4 +37,4 @@ Start-Process powershell.exe -WindowStyle Hidden -ArgumentList @( Start-Process $daemon -WindowStyle Hidden Add-Type -AssemblyName PresentationFramework -[System.Windows.MessageBox]::Show("Installed to $Dest`r`nCopy RCLONE_TEST to dropbox:, set enabled=true, then rclone-bisyncd --accept-resync.", 'rclone-dropbox-bisync') +[System.Windows.MessageBox]::Show("Installed to $Dest`r`nCopy RCLONE_TEST to dropbox: if missing. First run dry-runs then live --resync when both markers exist.", 'rclone-dropbox-bisync') diff --git a/windows/bootstrap.ps1 b/windows/bootstrap.ps1 index 13b1267..10caa91 100644 --- a/windows/bootstrap.ps1 +++ b/windows/bootstrap.ps1 @@ -97,7 +97,6 @@ Configured: workdir $Workdir session datastorage-dropbox (shared with Linux) daemon looping; 15 min after each run; mkdir lock -Copy RCLONE_TEST to dropbox:, set enabled=true, then: - rclone-bisyncd --accept-resync - (first run is --dry-run --resync until then) +If dropbox: has RCLONE_TEST and listings are missing, the daemon +dry-run --resync then live --resync on its own. Never after a failed run. "@