aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/cli/internal/doublestar/utils.go
diff options
context:
space:
mode:
author简律纯 <hsiangnianian@outlook.com>2023-04-28 01:36:44 +0800
committer简律纯 <hsiangnianian@outlook.com>2023-04-28 01:36:44 +0800
commitdd84b9d64fb98746a230cd24233ff50a562c39c9 (patch)
treeb583261ef00b3afe72ec4d6dacb31e57779a6faf /cli/internal/doublestar/utils.go
parent0b46fcd72ac34382387b2bcf9095233efbcc52f4 (diff)
downloadHydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.tar.gz
HydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.zip
Diffstat (limited to 'cli/internal/doublestar/utils.go')
-rw-r--r--cli/internal/doublestar/utils.go71
1 files changed, 71 insertions, 0 deletions
diff --git a/cli/internal/doublestar/utils.go b/cli/internal/doublestar/utils.go
new file mode 100644
index 0000000..7236cd0
--- /dev/null
+++ b/cli/internal/doublestar/utils.go
@@ -0,0 +1,71 @@
+// Package doublestar is adapted from https://github.com/bmatcuk/doublestar
+// Copyright Bob Matcuk. All Rights Reserved.
+// SPDX-License-Identifier: MIT
+package doublestar
+
+// SplitPattern is a utility function. Given a pattern, SplitPattern will
+// return two strings: the first string is everything up to the last slash
+// (`/`) that appears _before_ any unescaped "meta" characters (ie, `*?[{`).
+// The second string is everything after that slash. For example, given the
+// pattern:
+//
+// ../../path/to/meta*/**
+// ^----------- split here
+//
+// SplitPattern returns "../../path/to" and "meta*/**". This is useful for
+// initializing os.DirFS() to call Glob() because Glob() will silently fail if
+// your pattern includes `/./` or `/../`. For example:
+//
+// base, pattern := SplitPattern("../../path/to/meta*/**")
+// fsys := os.DirFS(base)
+// matches, err := Glob(fsys, pattern)
+//
+// If SplitPattern cannot find somewhere to split the pattern (for example,
+// `meta*/**`), it will return "." and the unaltered pattern (`meta*/**` in
+// this example).
+//
+// Of course, it is your responsibility to decide if the returned base path is
+// "safe" in the context of your application. Perhaps you could use Match() to
+// validate against a list of approved base directories?
+func SplitPattern(p string) (string, string) {
+ base := "."
+ pattern := p
+
+ splitIdx := -1
+ for i := 0; i < len(p); i++ {
+ c := p[i]
+ if c == '\\' {
+ i++
+ } else if c == '/' {
+ splitIdx = i
+ } else if c == '*' || c == '?' || c == '[' || c == '{' {
+ break
+ }
+ }
+
+ if splitIdx >= 0 {
+ return p[:splitIdx], p[splitIdx+1:]
+ }
+
+ return base, pattern
+}
+
+// Finds the next comma, but ignores any commas that appear inside nested `{}`.
+// Assumes that each opening bracket has a corresponding closing bracket.
+func indexNextAlt(s string, allowEscaping bool) int {
+ alts := 1
+ l := len(s)
+ for i := 0; i < l; i++ {
+ if allowEscaping && s[i] == '\\' {
+ // skip next byte
+ i++
+ } else if s[i] == '{' {
+ alts++
+ } else if s[i] == '}' {
+ alts--
+ } else if s[i] == ',' && alts == 1 {
+ return i
+ }
+ }
+ return -1
+}