summaryrefslogtreecommitdiffhomepage
path: root/util/pathutil
diff options
context:
space:
mode:
Diffstat (limited to 'util/pathutil')
-rw-r--r--util/pathutil/pathutil.go28
-rw-r--r--util/pathutil/pathutil_test.go37
2 files changed, 65 insertions, 0 deletions
diff --git a/util/pathutil/pathutil.go b/util/pathutil/pathutil.go
new file mode 100644
index 000000000..6b3728d9f
--- /dev/null
+++ b/util/pathutil/pathutil.go
@@ -0,0 +1,28 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+// package pathutil provides utility functions for working with URL paths.
+package pathutil
+
+import (
+ "path"
+ "strings"
+)
+
+const (
+ sepString = "/"
+ sepStringAndDot = "/."
+ sep = '/'
+)
+
+func Split(p string) []string {
+ return strings.Split(strings.Trim(path.Clean(p), sepStringAndDot), sepString)
+}
+
+func Join(parts ...string) string {
+ return sepString + strings.Join(parts, sepString)
+}
+
+func IsRoot(path string) bool {
+ return len(path) == 0 || len(path) == 1 && path[0] == sep
+}
diff --git a/util/pathutil/pathutil_test.go b/util/pathutil/pathutil_test.go
new file mode 100644
index 000000000..7ecc3787c
--- /dev/null
+++ b/util/pathutil/pathutil_test.go
@@ -0,0 +1,37 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package pathutil
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestSplit(t *testing.T) {
+ tests := []struct {
+ path string
+ want []string
+ }{
+ {"", []string{""}},
+ {"/", []string{""}},
+ {"//", []string{""}},
+ {"a", []string{"a"}},
+ {"/a", []string{"a"}},
+ {"a/", []string{"a"}},
+ {"/a/", []string{"a"}},
+ {"a/b", []string{"a", "b"}},
+ {"/a/b", []string{"a", "b"}},
+ {"a/b/", []string{"a", "b"}},
+ {"/a/b/", []string{"a", "b"}},
+ {"/a/../b", []string{"b"}},
+ }
+ for _, tt := range tests {
+ t.Run(tt.path, func(t *testing.T) {
+ if got := Split(tt.path); !reflect.DeepEqual(tt.want, got) {
+ t.Errorf("Split(%q) = %v; want %v", tt.path, got, tt.want)
+ }
+ })
+ }
+
+}