diff --git a/src/restic/backend/layout_cloud.go b/src/restic/backend/layout_cloud.go index 6a6947c59..dc79130a2 100644 --- a/src/restic/backend/layout_cloud.go +++ b/src/restic/backend/layout_cloud.go @@ -5,6 +5,7 @@ import "restic" // CloudLayout implements the default layout for cloud storage backends, as // described in the Design document. type CloudLayout struct { + URL string Path string Join func(...string) string } @@ -13,7 +14,7 @@ var cloudLayoutPaths = defaultLayoutPaths // Dirname returns the directory path for a given file type and name. func (l *CloudLayout) Dirname(h restic.Handle) string { - return l.Join(l.Path, cloudLayoutPaths[h.Type]) + return l.URL + l.Join(l.Path, "/", cloudLayoutPaths[h.Type]) } // Filename returns a path to a file, including its name. @@ -24,18 +25,18 @@ func (l *CloudLayout) Filename(h restic.Handle) string { name = "config" } - return l.Join(l.Dirname(h), name) + return l.URL + l.Join(l.Path, "/", cloudLayoutPaths[h.Type], name) } // Paths returns all directory names func (l *CloudLayout) Paths() (dirs []string) { for _, p := range cloudLayoutPaths { - dirs = append(dirs, l.Join(l.Path, p)) + dirs = append(dirs, l.URL+l.Join(l.Path, p)) } return dirs } // Basedir returns the base dir name for files of type t. func (l *CloudLayout) Basedir(t restic.FileType) string { - return l.Join(l.Path, cloudLayoutPaths[t]) + return l.URL + l.Join(l.Path, cloudLayoutPaths[t]) } diff --git a/src/restic/backend/layout_s3.go b/src/restic/backend/layout_s3.go index 42df63c3c..d2a034a4c 100644 --- a/src/restic/backend/layout_s3.go +++ b/src/restic/backend/layout_s3.go @@ -5,6 +5,7 @@ import "restic" // S3Layout implements the old layout used for s3 cloud storage backends, as // described in the Design document. type S3Layout struct { + URL string Path string Join func(...string) string } @@ -19,7 +20,7 @@ var s3LayoutPaths = map[restic.FileType]string{ // Dirname returns the directory path for a given file type and name. func (l *S3Layout) Dirname(h restic.Handle) string { - return l.Join(l.Path, s3LayoutPaths[h.Type]) + return l.URL + l.Join(l.Path, "/", s3LayoutPaths[h.Type]) } // Filename returns a path to a file, including its name. @@ -30,7 +31,7 @@ func (l *S3Layout) Filename(h restic.Handle) string { name = "config" } - return l.Join(l.Dirname(h), name) + return l.URL + l.Join(l.Path, "/", s3LayoutPaths[h.Type], name) } // Paths returns all directory names diff --git a/src/restic/backend/layout_test.go b/src/restic/backend/layout_test.go index dc1c231b9..9b270164d 100644 --- a/src/restic/backend/layout_test.go +++ b/src/restic/backend/layout_test.go @@ -2,6 +2,7 @@ package backend import ( "fmt" + "path" "path/filepath" "reflect" "restic" @@ -146,6 +147,54 @@ func TestCloudLayout(t *testing.T) { } } +func TestCloudLayoutURLs(t *testing.T) { + var tests = []struct { + l Layout + h restic.Handle + fn string + }{ + { + &CloudLayout{URL: "https://hostname.foo", Path: "", Join: path.Join}, + restic.Handle{Type: restic.DataFile, Name: "foobar"}, + "https://hostname.foo/data/foobar", + }, + { + &CloudLayout{URL: "https://hostname.foo:1234/prefix/repo", Path: "/", Join: path.Join}, + restic.Handle{Type: restic.LockFile, Name: "foobar"}, + "https://hostname.foo:1234/prefix/repo/locks/foobar", + }, + { + &CloudLayout{URL: "https://hostname.foo:1234/prefix/repo", Path: "/", Join: path.Join}, + restic.Handle{Type: restic.ConfigFile, Name: "foobar"}, + "https://hostname.foo:1234/prefix/repo/config", + }, + { + &S3Layout{URL: "https://hostname.foo", Path: "/", Join: path.Join}, + restic.Handle{Type: restic.DataFile, Name: "foobar"}, + "https://hostname.foo/data/foobar", + }, + { + &S3Layout{URL: "https://hostname.foo:1234/prefix/repo", Path: "", Join: path.Join}, + restic.Handle{Type: restic.LockFile, Name: "foobar"}, + "https://hostname.foo:1234/prefix/repo/lock/foobar", + }, + { + &S3Layout{URL: "https://hostname.foo:1234/prefix/repo", Path: "/", Join: path.Join}, + restic.Handle{Type: restic.ConfigFile, Name: "foobar"}, + "https://hostname.foo:1234/prefix/repo/config", + }, + } + + for _, test := range tests { + t.Run("cloud", func(t *testing.T) { + res := test.l.Filename(test.h) + if res != test.fn { + t.Fatalf("wrong filename, want %v, got %v", test.fn, res) + } + }) + } +} + func TestS3Layout(t *testing.T) { path, cleanup := TempDir(t) defer cleanup()