diff options
Diffstat (limited to 'internal/plan/fuzz_test.go')
| -rw-r--r-- | internal/plan/fuzz_test.go | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/internal/plan/fuzz_test.go b/internal/plan/fuzz_test.go index c7261ec..91a8421 100644 --- a/internal/plan/fuzz_test.go +++ b/internal/plan/fuzz_test.go @@ -56,7 +56,7 @@ func FuzzExpand(f *testing.F) { if got == "" { continue } - if base := textDir(dest, "/r", xdg.Home()); !underDir(got, base) { + if base, templated := textDir(dest, "/r", xdg.Home()); templated && !underDir(got, base) { t.Fatalf("destination %q planned %q for %q, outside %q, the directory its text names", dest, got, name, base) } } @@ -79,28 +79,43 @@ func plannedDir(dest, name string, captures []string, facts Facts) string { } // textDir is the directory a destination's text names before its first -// '{' (spec 15.1), worked out here by hand rather than by staticDir: the -// text up to the last '/' before the brace, "~" as the home directory, a -// relative path under root. -func textDir(dest, root, home string) string { - prefix := dest[:strings.IndexByte(dest, '{')] +// placeholder (spec 15.1), worked out here by hand rather than by staticDir: +// the text up to the last '/' before the first '{' that is not "{{", with +// "{{" and "}}" read as braces, "~" as the home directory, a relative path +// under root. templated is false when dest has no placeholder, only literal +// braces: then a ".." in it is the rule's own. +func textDir(dest, root, home string) (dir string, templated bool) { + open := 0 + for { + j := strings.IndexByte(dest[open:], '{') + if j < 0 { + return "", false + } + if open+j+1 < len(dest) && dest[open+j+1] == '{' { + open += j + 2 + continue + } + open += j + break + } + prefix := strings.NewReplacer("{{", "{", "}}", "}").Replace(dest[:open]) switch cut := strings.LastIndexByte(prefix, '/'); { case cut < 0: prefix = "" case cut == 0: - return "/" + return "/", true default: prefix = prefix[:cut] } switch { case prefix == "~": - return home + return home, true case strings.HasPrefix(prefix, "~/"): - return path.Join(home, prefix[2:]) + return path.Join(home, prefix[2:]), true case strings.HasPrefix(prefix, "/"): - return path.Clean(prefix) + return path.Clean(prefix), true } - return path.Join(root, prefix) + return path.Join(root, prefix), true } // underDir reports whether path is dir or lies under it, by whole segments. |
