Support attaching existing Restic repositories

This commit is contained in:
Mikei386
2026-06-15 12:01:24 +02:00
parent e97dde0ed8
commit 3327f21881
11 changed files with 115 additions and 15 deletions
+41
View File
@@ -0,0 +1,41 @@
package service
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestValidateExistingRepositoryPathAcceptsRepositoryRoot(t *testing.T) {
root := t.TempDir()
if err := os.WriteFile(filepath.Join(root, "config"), []byte("restic"), 0600); err != nil {
t.Fatal(err)
}
if err := validateExistingRepositoryPath(root); err != nil {
t.Fatalf("repository root rejected: %v", err)
}
}
func TestValidateExistingRepositoryPathSuggestsDirectChild(t *testing.T) {
root := t.TempDir()
repository := filepath.Join(root, "server-backup")
if err := os.Mkdir(repository, 0700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(repository, "config"), []byte("restic"), 0600); err != nil {
t.Fatal(err)
}
err := validateExistingRepositoryPath(root)
if err == nil || !strings.Contains(err.Error(), repository) {
t.Fatalf("missing repository suggestion: %v", err)
}
}
func TestValidateExistingRepositoryPathExplainsMissingConfig(t *testing.T) {
root := t.TempDir()
err := validateExistingRepositoryPath(root)
if err == nil || !strings.Contains(err.Error(), "config, data, index, keys und snapshots") {
t.Fatalf("missing layout guidance: %v", err)
}
}
+33
View File
@@ -262,10 +262,43 @@ func (s *Service) TestRepository(ctx context.Context, repoID string, initialize
if initialize {
return s.restic.Init(ctx, mounted.Repository)
}
if mounted.Repository.Type != model.RepositorySFTP {
if err := validateExistingRepositoryPath(mounted.Repository.Location); err != nil {
return err
}
}
_, err = s.restic.Snapshots(ctx, mounted.Repository)
return err
}
func validateExistingRepositoryPath(location string) error {
configPath := filepath.Join(location, "config")
if info, err := os.Stat(configPath); err == nil && !info.IsDir() {
return nil
}
entries, readErr := os.ReadDir(location)
if readErr != nil {
return fmt.Errorf("repository: Repository-Ordner %q kann nicht gelesen werden: %w", location, readErr)
}
candidates := make([]string, 0, 3)
for _, entry := range entries {
if !entry.IsDir() {
continue
}
candidate := filepath.Join(location, entry.Name())
if info, err := os.Stat(filepath.Join(candidate, "config")); err == nil && !info.IsDir() {
candidates = append(candidates, candidate)
if len(candidates) == 3 {
break
}
}
}
if len(candidates) > 0 {
return fmt.Errorf("repository: Im gewählten Ordner liegt keine Restic-config. Verwende direkt den Repository-Ordner: %s", strings.Join(candidates, ", "))
}
return fmt.Errorf("repository: Im gewählten Ordner %q wurde keine Restic-config gefunden. Ein vorhandenes Repository muss direkt auf den Ordner zeigen, der config, data, index, keys und snapshots enthält", location)
}
func (s *Service) UnlockRepository(ctx context.Context, repoID string) error {
repo, ok := s.repository(repoID)
if !ok {