mirror of https://github.com/goharbor/harbor.git
feat: add regex filter for replication
Signed-off-by: TMHBOFH <itsystem.bofh@gmail.com>
This commit is contained in:
parent
0cf2d7545d
commit
9596eff009
|
@ -16,6 +16,7 @@ package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/bmatcuk/doublestar"
|
"github.com/bmatcuk/doublestar"
|
||||||
|
@ -26,6 +27,14 @@ func Match(pattern, str string) (bool, error) {
|
||||||
if len(pattern) == 0 {
|
if len(pattern) == 0 {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(pattern, "regex:") {
|
||||||
|
regexPattern := strings.TrimPrefix(pattern, "regex:")
|
||||||
|
reg, err := regexp.Compile(regexPattern)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("invalid regex pattern: %w", err)
|
||||||
|
}
|
||||||
|
return reg.MatchString(str), nil
|
||||||
|
}
|
||||||
return doublestar.Match(pattern, str)
|
return doublestar.Match(pattern, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,11 +83,63 @@ func TestMatch(t *testing.T) {
|
||||||
str: "v2.7.0",
|
str: "v2.7.0",
|
||||||
match: true,
|
match: true,
|
||||||
},
|
},
|
||||||
|
// New regex-based tests
|
||||||
|
{
|
||||||
|
pattern: "regex:^v1\\.[0-9]+$",
|
||||||
|
str: "v1.0",
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^v1\\.[0-9]+$",
|
||||||
|
str: "v1.10",
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^v1\\.[0-9]+$",
|
||||||
|
str: "v2.0",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^feature/.+$",
|
||||||
|
str: "feature/abc",
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^feature/.+$",
|
||||||
|
str: "bugfix/abc",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^(v|release)-\\d+\\.\\d+(\\.\\d+)?$",
|
||||||
|
str: "v-1.2.3",
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^(v|release)-\\d+\\.\\d+(\\.\\d+)?$",
|
||||||
|
str: "release-2.0",
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^(v|release)-\\d+\\.\\d+(\\.\\d+)?$",
|
||||||
|
str: "v-2",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^hotfix-(issue|bug)-[0-9]{4,}$",
|
||||||
|
str: "hotfix-bug-1234",
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "regex:^hotfix-(issue|bug)-[0-9]{4,}$",
|
||||||
|
str: "hotfix-feature-1234",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for i, c := range cases {
|
||||||
|
fmt.Printf("running case %d ...\n", i)
|
||||||
match, err := Match(c.pattern, c.str)
|
match, err := Match(c.pattern, c.str)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err, "unexpected error for pattern: %s", c.pattern)
|
||||||
assert.Equal(t, c.match, match)
|
assert.Equal(t, c.match, match, "pattern: %s, str: %s", c.pattern, c.str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +196,21 @@ func TestIsSpecificPathComponent(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatch_InvalidRegex(t *testing.T) {
|
||||||
|
invalidPatterns := []string{
|
||||||
|
"regex:^v[0-9+$", // missing closing bracket
|
||||||
|
"regex:(abc", // unclosed group
|
||||||
|
"regex:*abc", // invalid quantifier at start
|
||||||
|
"regex:[a-z", // incomplete character class
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, pattern := range invalidPatterns {
|
||||||
|
fmt.Printf("[TestMatch_InvalidRegex case %d] pattern=%q\n", i, pattern)
|
||||||
|
_, err := Match(pattern, "test-tag")
|
||||||
|
assert.Error(t, err, "expected error for invalid pattern: %s", pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsSpecificPath(t *testing.T) {
|
func TestIsSpecificPath(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
path string
|
path string
|
||||||
|
|
Loading…
Reference in New Issue