restic: treat 'config file already exists' on init as soft success
Re-running restic init on a repo that's already initialised exits non-zero with "Fatal: ... config file already exists". Semantically that's a no-op, not a failure — the repo IS initialised, the caller's intent is satisfied. Sniff stderr for the magic string and swallow the exit code in that case, emitting an event line so the operator-facing log says what happened. Caught while smoke-testing P2-04.5: I'd init'd the repo manually during a debug session, then the operator clicking the UI's Init-repo button would hit this and the host's repo_initialised_at would never flip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -173,15 +173,36 @@ func (e Env) RunInit(ctx context.Context, handle LineHandler) error {
|
||||
return fmt.Errorf("restic init: start: %w", err)
|
||||
}
|
||||
|
||||
// Sniff for "config file already exists" on stderr; if we see it
|
||||
// we'll treat the non-zero exit as a soft success — running init
|
||||
// against an already-initialised repo is a no-op semantically,
|
||||
// not a failure. Wraps the caller's handle so the line still
|
||||
// gets streamed verbatim to the operator-facing log.
|
||||
alreadyInited := false
|
||||
sniff := func(stream, line string, ev any) {
|
||||
if stream == "stderr" && strings.Contains(line, "config file already exists") {
|
||||
alreadyInited = true
|
||||
}
|
||||
if handle != nil {
|
||||
handle(stream, line, ev)
|
||||
}
|
||||
}
|
||||
|
||||
done := make(chan error, 2)
|
||||
go func() { done <- pumpPlain(stdout, "stdout", handle) }()
|
||||
go func() { done <- pumpPlain(stderr, "stderr", handle) }()
|
||||
go func() { done <- pumpPlain(stdout, "stdout", sniff) }()
|
||||
go func() { done <- pumpPlain(stderr, "stderr", sniff) }()
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := <-done; err != nil && handle != nil {
|
||||
handle("event", fmt.Sprintf("pump error: %v", err), nil)
|
||||
}
|
||||
}
|
||||
if werr := cmd.Wait(); werr != nil {
|
||||
if alreadyInited {
|
||||
if handle != nil {
|
||||
handle("event", "repo already initialised — treating as success", nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("restic init: %w", werr)
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user