Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 2c8c9e2

Browse files
committed
Implement GlobPath() extension method for comparing glob paths
1 parent ec161ee commit 2c8c9e2

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

src/ServiceStack.Text/StringExtensions.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,56 @@ public static bool Glob(this string value, string pattern)
10701070
return value.Length == pos;
10711071
}
10721072

1073+
public static bool GlobPath(this string filePath, string pattern)
1074+
{
1075+
if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(pattern))
1076+
return false;
1077+
1078+
var sanitizedPath = filePath.Replace('\\','/');
1079+
if (sanitizedPath[0] == '/')
1080+
sanitizedPath = sanitizedPath.Substring(1);
1081+
var sanitizedPattern = pattern.Replace('\\', '/');
1082+
if (sanitizedPattern[0] == '/')
1083+
sanitizedPattern = sanitizedPattern.Substring(1);
1084+
1085+
if (sanitizedPattern.IndexOf('*') == -1 && sanitizedPattern.IndexOf('?') == -1)
1086+
return sanitizedPath == sanitizedPattern;
1087+
1088+
var patternParts = sanitizedPattern.SplitOnLast('/');
1089+
var parts = sanitizedPath.SplitOnLast('/');
1090+
if (parts.Length == 1)
1091+
return parts[0].Glob(pattern);
1092+
1093+
var dirPart = parts[0];
1094+
var filePart = parts[1];
1095+
if (patternParts.Length == 1)
1096+
return filePart.Glob(patternParts[0]);
1097+
1098+
var dirPattern = patternParts[0];
1099+
var filePattern = patternParts[1];
1100+
1101+
if (dirPattern.IndexOf("**", StringComparison.Ordinal) >= 0)
1102+
{
1103+
if (!dirPart.StartsWith(dirPattern.LeftPart("**").TrimEnd('*')))
1104+
return false;
1105+
}
1106+
else if (dirPattern.IndexOf('*') >= 0 || dirPattern.IndexOf('?') >= 0)
1107+
{
1108+
var regex = new Regex(
1109+
"^" + Regex.Escape(dirPattern).Replace(@"\*", "[^\\/]*").Replace(@"\?", ".") + "$"
1110+
);
1111+
if (!regex.IsMatch(dirPart))
1112+
return false;
1113+
}
1114+
else
1115+
{
1116+
if (dirPart != dirPattern)
1117+
return false;
1118+
}
1119+
1120+
return filePart.Glob(filePattern);
1121+
}
1122+
10731123
public static string TrimPrefixes(this string fromString, params string[] prefixes)
10741124
{
10751125
if (string.IsNullOrEmpty(fromString))
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using NUnit.Framework;
2+
using ServiceStack;
3+
using ServiceStack.Text;
4+
5+
namespace ServiceStack.Text.Tests
6+
{
7+
[TestFixture]
8+
public class GlobPathTests
9+
{
10+
[Test]
11+
public void Does_validate_GlobPaths()
12+
{
13+
Assert.That(!"/dir/a/file.txt".GlobPath(""));
14+
Assert.That(!"".GlobPath("*.txt"));
15+
Assert.That("file.txt".GlobPath("file.txt"));
16+
Assert.That(!"file.txt".GlobPath("file.json"));
17+
Assert.That(!"file.txt".GlobPath("*.json"));
18+
Assert.That("file.txt".GlobPath("*.txt"));
19+
20+
Assert.That("/dir/a/file.txt".GlobPath("/dir/a/file.txt"));
21+
Assert.That("dir\\a/file.txt".GlobPath("/dir/a/file.txt"));
22+
Assert.That("/dir/a/file.txt".GlobPath("dir\\a/file.txt"));
23+
Assert.That(!"/dir/a/file.txt".GlobPath("/dir/b/file.txt"));
24+
Assert.That(!"/dir/a/file.txt".GlobPath("/dir/a/file2.txt"));
25+
Assert.That(!"/dir/a/file.txt".GlobPath("dir\\a/file2.txt"));
26+
Assert.That(!"/Dir/a/file.txt".GlobPath("/dir/a/file2.txt"));
27+
Assert.That(!"/dir1/a/file.txt".GlobPath("/dir2/a/file2.txt"));
28+
Assert.That(!"/dir/a/file.txt".GlobPath("/dir/a/file.json"));
29+
Assert.That(!"/dir/a/file.txt".GlobPath("/dir/a/file2.txt"));
30+
Assert.That(!"/dir/a/file.txt".GlobPath("/dir/a/file2.*"));
31+
Assert.That(!"/dir/a/file.txt".GlobPath("/dir/a/*.json"));
32+
33+
Assert.That("dir/a/file.txt".GlobPath("dir/*/file.txt"));
34+
Assert.That(!"dir/file.txt".GlobPath("dir/*/file.txt"));
35+
Assert.That(!"dir/a/b/file.txt".GlobPath("dir/*/file.txt"));
36+
Assert.That("dir/ab/file.txt".GlobPath("dir/a*/file.txt"));
37+
Assert.That("dir/abc/file.txt".GlobPath("dir/a*/file.txt"));
38+
Assert.That("dir/ab/file.txt".GlobPath("dir/a?/file.txt"));
39+
Assert.That(!"dir/abc/file.txt".GlobPath("dir/a?/file.txt"));
40+
Assert.That("dir/abc/file.txt".GlobPath("dir/a?c/file.txt"));
41+
42+
Assert.That("dir/a/file.txt".GlobPath("dir/**/file.txt"));
43+
Assert.That("dir/a/b/file.txt".GlobPath("dir/**/file.txt"));
44+
Assert.That("dir/a/b/c/d/e/file.txt".GlobPath("dir/**/file.txt"));
45+
Assert.That("dir/a/b/c/d/e/file.json".GlobPath("dir/**/*.json"));
46+
}
47+
}
48+
}

tests/ServiceStack.Text.Tests/ServiceStack.Text.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@
191191
<Compile Include="EnumerableTests.cs" />
192192
<Compile Include="AttributeTests.cs" />
193193
<Compile Include="CsvTypeTests.cs" />
194+
<Compile Include="GlobPathTests.cs" />
194195
<Compile Include="HttpUtilsTests.cs" />
195196
<Compile Include="Issues\JsConfigIssues.cs" />
196197
<Compile Include="JsonTests\InheritAbstractTests.cs" />

0 commit comments

Comments
 (0)