diff --git a/lib/bucket/bucket.go b/lib/bucket/bucket.go index a9c63b83d..d019d13b8 100644 --- a/lib/bucket/bucket.go +++ b/lib/bucket/bucket.go @@ -29,6 +29,23 @@ func Split(absPath string) (bucket, bucketPath string) { return absPath[:slash], absPath[slash+1:] } +// Join joins any number of path elements into a single path, adding a +// separating slash if necessary. Empty elements are ignored. +// +// Unlike path.Join this does not run path.Clean on the elements so a +// path called "." will be preserved. +func Join(elem ...string) (out string) { + for _, e := range elem { + if e != "" { + if out != "" { + out += "/" + } + out += e + } + } + return out +} + // Cache stores whether buckets are available and their IDs type Cache struct { mu sync.Mutex // mutex to protect created and deleted diff --git a/lib/bucket/bucket_test.go b/lib/bucket/bucket_test.go index c178a37f9..5594655aa 100644 --- a/lib/bucket/bucket_test.go +++ b/lib/bucket/bucket_test.go @@ -2,6 +2,7 @@ package bucket import ( "errors" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -24,6 +25,25 @@ func TestSplit(t *testing.T) { } } +func TestJoin(t *testing.T) { + for _, test := range []struct { + in []string + want string + }{ + {in: []string{}, want: ""}, + {in: []string{""}, want: ""}, + {in: []string{"", ""}, want: ""}, + {in: []string{"", "b"}, want: "b"}, + {in: []string{"a", ""}, want: "a"}, + {in: []string{"a", "b"}, want: "a/b"}, + {in: []string{"a/b/c", "..", "."}, want: "a/b/c/../."}, + } { + got := Join(test.in...) + what := fmt.Sprintf("Join(%q)", test.in) + assert.Equal(t, test.want, got, what) + } +} + func TestCache(t *testing.T) { c := NewCache() errBoom := errors.New("boom")