diff --git a/TODO.md b/TODO.md index c8bab67..28dc127 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,7 @@ # TODO - [ ] Write README -- [ ] `restic backup` can take a long time: stream output to logging somehow to keep track of what it's doing. +- [X] `restic backup` can take a long time: stream output to logging somehow to keep track of what it's doing. Stop using `--json` for `backup`, generates way too much JSON log info. - [ ] Make Restictray non-dependent on existing config in `~/.restic`: - [ ] Create default files if not existing? - [ ] Create a config dialog in https://developer.fyne.io/ @@ -11,4 +11,6 @@ - [ ] If something goes wrong, menu shows error and app becomes unusable. Perhaps not all errors (e.g. above one) have to be this way. - [X] Is backing up while mounted ok? => yes - [ ] `restic backup` can result in `Warning: at least one source file could not be read\n: exit status 3`. This returns an error, but the backup itself seems to be all right. + - [X] exit code 3: https://restic.readthedocs.io/en/stable/040_backup.html likely to be a permission problem, perhaps ignoring instead of panicking as of now? + - [ ] `restic list locks` showed a dangling one; PID of already gone `restic` process. Why? Unable to reproduce? - [ ] Verify backups with `restic check`? If not okay, remove (snapshot/folder?) and rebackup? What's the plan then? \ No newline at end of file diff --git a/restic/wrapper.go b/restic/wrapper.go index 2e15f5f..36dcb8d 100644 --- a/restic/wrapper.go +++ b/restic/wrapper.go @@ -1,7 +1,9 @@ package restic import ( + "bufio" "encoding/json" + "errors" "fmt" "github.com/rs/zerolog/log" "os/exec" @@ -139,12 +141,28 @@ func openFolder(folder string) error { return nil } +// Backup uses "restic backup" to create a new snapshot. This is a blocking call. func (w *Wrapper) Backup(c *Config) error { - cmd := resticCmd("--json", "--password-file", PasswordFile(), "-r", c.Repository, "--exclude-file", ExcludeFile(), "backup", c.Backup) - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("restic backup cmd: %s: %w", string(out), err) + cmd := resticCmd("--password-file", PasswordFile(), "-r", c.Repository, "--exclude-file", ExcludeFile(), "backup", c.Backup, "--no-scan") + + stdout, _ := cmd.StdoutPipe() + cmd.Start() + + scanner := bufio.NewScanner(stdout) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + m := scanner.Text() + log.Info().Str("out", m).Msg("backup") + } + err := cmd.Wait() + + if err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && exitErr.ExitCode() == 3 { + log.Warn().Err(err).Msg("At least one file could not be read, permission problem?") + return nil + } + return fmt.Errorf("restic backup cmd: %w", err) } - log.Info().Str("out", string(out)).Msg("backup") return nil }