mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-02 14:46:31 +00:00
96828b16c1
* Support glob with doublestar for path conditions * Update docs and pipeline
69 lines
1.9 KiB
Go
69 lines
1.9 KiB
Go
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) (base, pattern 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
|
|
}
|
|
|
|
// 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
|
|
}
|