mirror of
https://github.com/goharbor/harbor.git
synced 2024-09-29 05:47:31 +02:00
122 lines
3.7 KiB
Go
122 lines
3.7 KiB
Go
|
// Copyright Project Harbor Authors
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package util
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/bmatcuk/doublestar"
|
||
|
)
|
||
|
|
||
|
// Match returns whether the str matches the pattern
|
||
|
func Match(pattern, str string) (bool, error) {
|
||
|
if len(pattern) == 0 {
|
||
|
return true, nil
|
||
|
}
|
||
|
return doublestar.Match(pattern, str)
|
||
|
}
|
||
|
|
||
|
// IsSpecificPath checks whether the input path is a specified string
|
||
|
// If it is, the function returns a string array that parsed from the input path
|
||
|
// A specified string means we can get a specific string array after parsing it
|
||
|
// "library/hello-world" is a specified string as it only matches "library/hello-world"
|
||
|
// "library/**" isn't a specified string as it can match all string that starts with "library/"
|
||
|
// "library/{test,busybox}" is a specified string as it only matches "library/hello-world" and "library/busybox"
|
||
|
func IsSpecificPath(path string) ([]string, bool) {
|
||
|
if len(path) == 0 {
|
||
|
return nil, false
|
||
|
}
|
||
|
components := [][]string{}
|
||
|
for _, component := range strings.Split(path, "/") {
|
||
|
strs, ok := IsSpecificPathComponent(component)
|
||
|
if !ok {
|
||
|
return nil, false
|
||
|
}
|
||
|
components = append(components, strs)
|
||
|
}
|
||
|
|
||
|
result := []string{}
|
||
|
for _, component := range components {
|
||
|
result = combinationPathComponents(result, component)
|
||
|
}
|
||
|
return result, true
|
||
|
}
|
||
|
|
||
|
func combinationPathComponents(components1, components2 []string) []string {
|
||
|
if len(components1) == 0 {
|
||
|
return components2
|
||
|
}
|
||
|
if len(components2) == 0 {
|
||
|
return components1
|
||
|
}
|
||
|
components := []string{}
|
||
|
for _, component1 := range components1 {
|
||
|
for _, component2 := range components2 {
|
||
|
components = append(components, fmt.Sprintf("%s/%s", component1, component2))
|
||
|
}
|
||
|
}
|
||
|
return components
|
||
|
}
|
||
|
|
||
|
// IsSpecificPathComponent checks whether the input path component is a specified string
|
||
|
// If it is, the function returns a string array that parsed from the input component
|
||
|
// A specified string means we can get a specific string array after parsing it
|
||
|
// "library" is a specified string as it only matches "library"
|
||
|
// "library*" isn't a specified string as it can match all string that starts with "library"
|
||
|
// "{library, test}" is a specified string as it only matches "library" and "test"
|
||
|
// Note: the function doesn't support the component that contains more than one "{"
|
||
|
// such as "a{b{c,d}e}f"
|
||
|
func IsSpecificPathComponent(component string) ([]string, bool) {
|
||
|
if len(component) == 0 {
|
||
|
return nil, false
|
||
|
}
|
||
|
// contains any of *?[\\]^
|
||
|
if strings.ContainsAny(component, "*?[\\]^/") {
|
||
|
return nil, false
|
||
|
}
|
||
|
// doesn't contain {},
|
||
|
if !strings.ContainsAny(component, "{},") {
|
||
|
return []string{component}, true
|
||
|
}
|
||
|
// support only one pair of {} currently
|
||
|
n := strings.Count(component, "{")
|
||
|
if n > 1 {
|
||
|
return nil, false
|
||
|
}
|
||
|
i := strings.Index(component, "{")
|
||
|
if i == -1 {
|
||
|
return nil, false
|
||
|
}
|
||
|
j := strings.LastIndex(component, "}")
|
||
|
if j == -1 {
|
||
|
return nil, false
|
||
|
}
|
||
|
if i > j {
|
||
|
return nil, false
|
||
|
}
|
||
|
prefix := component[:i]
|
||
|
suffix := ""
|
||
|
if j+1 < len(component) {
|
||
|
suffix = component[j+1:]
|
||
|
}
|
||
|
components := []string{}
|
||
|
strs := strings.Split(component[i+1:j], ",")
|
||
|
for _, str := range strs {
|
||
|
components = append(components, prefix+str+suffix)
|
||
|
}
|
||
|
return components, true
|
||
|
}
|