mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
fix pattern logic
This commit is contained in:
committed by
harsh mahajan
parent
a4f174ea7e
commit
e17cdc2bd4
@@ -21,24 +21,48 @@ class BuildTrigger extends Validator
|
||||
$include = array_filter($this->patterns, fn ($p) => !str_starts_with($p, '!'));
|
||||
$exclude = array_filter($this->patterns, fn ($p) => str_starts_with($p, '!'));
|
||||
|
||||
if (empty($include)) {
|
||||
// Only exclusions: pass everything unless excluded.
|
||||
foreach ($exclude as $pattern) {
|
||||
if ($this->matchGlob($value, substr($pattern, 1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// A pattern is "specific" when it contains no wildcard characters.
|
||||
$isSpecific = fn($p) => !str_contains($p, '*') && !str_contains($p, '?');
|
||||
|
||||
// 1. Specific inclusion always wins — an explicit exact match is never blocked.
|
||||
foreach ($include as $pattern) {
|
||||
if ($this->matchGlob($value, $pattern)) {
|
||||
if ($isSpecific($pattern) && $this->matchGlob($value, $pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Specific exclusion overrides a wildcard inclusion — refines broad patterns.
|
||||
foreach ($exclude as $pattern) {
|
||||
if ($this->matchGlob($value, substr($pattern, 1))) {
|
||||
$raw = substr($pattern, 1);
|
||||
if ($isSpecific($raw) && $this->matchGlob($value, $raw)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return empty($include);
|
||||
// 3. Wildcard inclusion wins over any remaining wildcard exclusion.
|
||||
foreach ($include as $pattern) {
|
||||
if (!$isSpecific($pattern) && $this->matchGlob($value, $pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No inclusion matched.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Value must match at least one inclusion pattern and must not match any exclusion pattern.';
|
||||
return 'Value must match a specific inclusion, or a wildcard inclusion not overridden by a specific exclusion.';
|
||||
}
|
||||
|
||||
public function isArray(): bool
|
||||
|
||||
@@ -59,6 +59,34 @@ class BuildTriggerTest extends TestCase
|
||||
$this->assertFalse($validator->isValid('feature/test'));
|
||||
}
|
||||
|
||||
public function testQuestionMarkWildcard(): void
|
||||
{
|
||||
$validator = new BuildTrigger(['v?.?']);
|
||||
$this->assertTrue($validator->isValid('v1.0'));
|
||||
$this->assertTrue($validator->isValid('v2.5'));
|
||||
$this->assertFalse($validator->isValid('v10.0')); // ? matches exactly one char, not two
|
||||
$this->assertFalse($validator->isValid('v1/0')); // ? does not cross /
|
||||
}
|
||||
|
||||
public function testQuestionMarkDoesNotCrossSlash(): void
|
||||
{
|
||||
$validator = new BuildTrigger(['feature/?']);
|
||||
$this->assertTrue($validator->isValid('feature/a'));
|
||||
$this->assertTrue($validator->isValid('feature/z'));
|
||||
$this->assertFalse($validator->isValid('feature/ab')); // ? matches only one char
|
||||
$this->assertFalse($validator->isValid('feature/a/b')); // ? does not cross /
|
||||
$this->assertFalse($validator->isValid('feature/'));
|
||||
}
|
||||
|
||||
public function testQuestionMarkMixedWithStar(): void
|
||||
{
|
||||
$validator = new BuildTrigger(['fix-?.*']);
|
||||
$this->assertTrue($validator->isValid('fix-1.php'));
|
||||
$this->assertTrue($validator->isValid('fix-a.js'));
|
||||
$this->assertFalse($validator->isValid('fix-12.php')); // ? matches only one char
|
||||
$this->assertFalse($validator->isValid('fix-.php')); // ? requires exactly one char
|
||||
}
|
||||
|
||||
public function testDoubleWildcardAtEnd(): void
|
||||
{
|
||||
$validator = new BuildTrigger(['src/**']);
|
||||
@@ -169,36 +197,36 @@ class BuildTriggerTest extends TestCase
|
||||
|
||||
public function testMultipleInclusionsWithSingleExclusion(): void
|
||||
{
|
||||
// feature/wip matches the inclusion feature/* → true (exclusion !feature/wip is never reached)
|
||||
// feature/wip matches wildcard inclusion feature/* but specific exclusion !feature/wip overrides it
|
||||
$validator = new BuildTrigger(['main', 'develop', 'feature/*', '!feature/wip']);
|
||||
$this->assertTrue($validator->isValid('main'));
|
||||
$this->assertTrue($validator->isValid('develop'));
|
||||
$this->assertTrue($validator->isValid('feature/foo'));
|
||||
$this->assertTrue($validator->isValid('feature/wip')); // inclusion wins
|
||||
$this->assertFalse($validator->isValid('feature/wip')); // specific exclusion overrides wildcard inclusion
|
||||
$this->assertFalse($validator->isValid('hotfix/urgent')); // no inclusion match
|
||||
}
|
||||
|
||||
public function testSingleInclusionWithMultipleExclusions(): void
|
||||
{
|
||||
// feature/wip and feature/experimental both match the inclusion feature/** → true
|
||||
// specific exclusions !feature/wip and !feature/experimental override wildcard inclusion feature/**
|
||||
$validator = new BuildTrigger(['feature/**', '!feature/wip', '!feature/experimental']);
|
||||
$this->assertTrue($validator->isValid('feature/foo'));
|
||||
$this->assertTrue($validator->isValid('feature/a/b'));
|
||||
$this->assertTrue($validator->isValid('feature/wip')); // inclusion wins
|
||||
$this->assertTrue($validator->isValid('feature/experimental')); // inclusion wins
|
||||
$this->assertFalse($validator->isValid('main')); // no inclusion match
|
||||
$this->assertFalse($validator->isValid('feature/wip')); // specific exclusion wins
|
||||
$this->assertFalse($validator->isValid('feature/experimental')); // specific exclusion wins
|
||||
$this->assertFalse($validator->isValid('main')); // no inclusion match
|
||||
}
|
||||
|
||||
public function testMultipleInclusionsWithMultipleExclusions(): void
|
||||
{
|
||||
// feature/wip and feature/experimental both match the inclusion feature/** → true
|
||||
// specific exclusions override the wildcard inclusion; specific inclusion 'main' is unaffected
|
||||
$validator = new BuildTrigger(['main', 'feature/**', '!feature/wip', '!feature/experimental']);
|
||||
$this->assertTrue($validator->isValid('main'));
|
||||
$this->assertTrue($validator->isValid('main')); // specific inclusion wins regardless
|
||||
$this->assertTrue($validator->isValid('feature/foo'));
|
||||
$this->assertTrue($validator->isValid('feature/a/b'));
|
||||
$this->assertTrue($validator->isValid('feature/wip')); // inclusion wins
|
||||
$this->assertTrue($validator->isValid('feature/experimental')); // inclusion wins
|
||||
$this->assertFalse($validator->isValid('develop')); // no inclusion match
|
||||
$this->assertFalse($validator->isValid('feature/wip')); // specific exclusion wins
|
||||
$this->assertFalse($validator->isValid('feature/experimental')); // specific exclusion wins
|
||||
$this->assertFalse($validator->isValid('develop')); // no inclusion match
|
||||
}
|
||||
|
||||
public function testSpecificInclusionOverridesWildcardExclusion(): void
|
||||
|
||||
Reference in New Issue
Block a user