diff --git a/util/util.go b/util/util.go index 3c7facfd..9bbc04cf 100644 --- a/util/util.go +++ b/util/util.go @@ -398,6 +398,29 @@ func RemovePathPrefix(s string) (string, error) { return "/" + strings.Join(x, "/"), nil } +// RemovePathSuffix takes an absolute path and removes the last chunk. It +// returns the remainder as an absolute path. This function is a bit of a hack, +// and could probably be re-written to support any kind of path, and return a +// relative path. +func RemovePathSuffix(s string) (string, error) { + if !strings.HasPrefix(s, "/") { + return "", fmt.Errorf("must be absolute") + } + // this is the PathSplit logic... + if s == "/" { + //return "", nil // TODO: return this instead? + return "", fmt.Errorf("input is /") + } + x := strings.Split(s, "/") + + // get rid of the last two chunks, last is / and second to last is a dir + if strings.HasSuffix(s, "/") { + _, x = x[len(x)-1], x[:len(x)-1] // pop the last slash + } + _, x = x[len(x)-1], x[:len(x)-1] // pop the last chunk + return strings.Join(x, "/") + "/", nil +} + // TimeAfterOrBlock is aspecial version of time.After that blocks when given a // negative integer. When used in a case statement, the timer restarts on each // select call to it. diff --git a/util/util_test.go b/util/util_test.go index b80c5f9a..0eddb9a1 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -1015,6 +1015,46 @@ func TestRemovePathPrefix0(t *testing.T) { } } +func TestRemovePathSuffix0(t *testing.T) { + testCases := []struct { + in string + out string + }{ + { + in: "/simple1/", + out: "/", + }, + { + in: "/simple1/foo/bar/", + out: "/simple1/foo/", + }, + { + in: "/simple1/foo/", + out: "/simple1/", + }, + // TODO: are these what we want? + { + in: "/simple1/foo", + out: "/simple1/", + }, + { + in: "/simple1", + out: "/", + }, + } + for _, test := range testCases { + out, err := RemovePathSuffix(test.in) + if err != nil { + t.Errorf("error: %+v", err) + continue + } + if test.out != out { + t.Errorf("failed: %s -> %s (exp: %s)", test.in, out, test.out) + continue + } + } +} + func TestPriorityStrSliceSort0(t *testing.T) { in := []string{"foo", "bar", "baz"} ex := []string{"bar", "baz", "foo"}