Skip to content

Commit b608bfc

Browse files
committed
Add StringComparison to file/directory extensions, with hearistic for default for IsSubPathOf
1 parent 3a2ef35 commit b608bfc

File tree

2 files changed

+91
-6
lines changed

2 files changed

+91
-6
lines changed

src/Elastic.Documentation/Extensions/IFileInfoExtensions.cs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System.Globalization;
56
using System.IO.Abstractions;
7+
using static System.StringComparison;
68

79
namespace Elastic.Documentation.Extensions;
810

@@ -26,7 +28,7 @@ public static bool IsSubPathOf(this IFileInfo file, IDirectoryInfo parentDirecto
2628
return parent is not null && parent.IsSubPathOf(parentDirectory);
2729
}
2830

29-
/// Checks if <paramref name="file"/> has parent directory <paramref name="parentName"/>
31+
/// Checks if <paramref name="file"/> has parent directory <paramref name="parentName"/>, defaults to OrdinalIgnoreCase comparison
3032
public static bool HasParent(this IFileInfo file, string parentName)
3133
{
3234
var parent = file.Directory;
@@ -36,29 +38,57 @@ public static bool HasParent(this IFileInfo file, string parentName)
3638

3739
public static class IDirectoryInfoExtensions
3840
{
41+
private static bool? CaseSensitiveOsCheck;
42+
public static bool IsCaseSensitiveFileSystem
43+
{
44+
45+
get
46+
{
47+
// heuristic to determine if the OS is case-sensitive
48+
try
49+
{
50+
var tmp = Path.GetTempPath();
51+
if (CaseSensitiveOsCheck.HasValue)
52+
return CaseSensitiveOsCheck.Value;
53+
var culture = CultureInfo.CurrentCulture;
54+
CaseSensitiveOsCheck = !Directory.Exists(tmp.ToUpper(culture)) || !Directory.Exists(tmp.ToLower(culture));
55+
return CaseSensitiveOsCheck ?? false;
56+
57+
}
58+
catch
59+
{
60+
// fallback to case-insensitive unless it's linux
61+
CaseSensitiveOsCheck = Environment.OSVersion.Platform == PlatformID.Unix;
62+
return false;
63+
}
64+
}
65+
}
66+
67+
3968
/// Validates <paramref name="directory"/> is subdirectory of <paramref name="parentDirectory"/>
4069
public static bool IsSubPathOf(this IDirectoryInfo directory, IDirectoryInfo parentDirectory)
4170
{
71+
var cmp = IsCaseSensitiveFileSystem ? Ordinal : OrdinalIgnoreCase;
4272
var parent = directory;
4373
do
4474
{
45-
if (parent.FullName == parentDirectory.FullName)
75+
if (string.Equals(parent.FullName, parentDirectory.FullName, cmp))
4676
return true;
4777
parent = parent.Parent;
4878
} while (parent != null);
4979

5080
return false;
5181
}
5282

53-
/// Checks if <paramref name="directory"/> has parent directory <paramref name="parentName"/>
54-
public static bool HasParent(this IDirectoryInfo directory, string parentName)
83+
/// Checks if <paramref name="directory"/> has parent directory <paramref name="parentName"/>, defaults to OrdinalIgnoreCase comparison
84+
public static bool HasParent(this IDirectoryInfo directory, string parentName, StringComparison comparison = OrdinalIgnoreCase)
5585
{
56-
if (directory.Name == parentName)
86+
if (string.Equals(directory.Name, parentName, comparison))
5787
return true;
5888
var parent = directory;
5989
do
6090
{
61-
if (parent.Name == parentName)
91+
if (string.Equals(parent.Name, parentName, comparison))
6292
return true;
6393
parent = parent.Parent;
6494
} while (parent != null);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.IO.Abstractions.TestingHelpers;
6+
using Elastic.Documentation;
7+
using Elastic.Documentation.Configuration;
8+
using Elastic.Documentation.Configuration.Versions;
9+
using Elastic.Documentation.Diagnostics;
10+
using Elastic.Documentation.Extensions;
11+
using Elastic.Markdown.IO;
12+
using FluentAssertions;
13+
14+
namespace Elastic.Markdown.Tests;
15+
16+
public class FileSystemExtensionsTest(ITestOutputHelper output)
17+
{
18+
[Fact]
19+
public void IsSubPathOfTests()
20+
{
21+
var fs = new MockFileSystem();
22+
23+
fs.DirectoryInfo.New("/a/b/c/d").IsSubPathOf(fs.DirectoryInfo.New("/a/b/c/d/e/f")).Should().BeFalse();
24+
fs.DirectoryInfo.New("/a/b/c/d/e/f").IsSubPathOf(fs.DirectoryInfo.New("/a/b/c/d")).Should().BeTrue();
25+
26+
var caseSensitive = IDirectoryInfoExtensions.IsCaseSensitiveFileSystem;
27+
28+
if (caseSensitive)
29+
{
30+
fs.DirectoryInfo.New("/a/b/C/d/e/f").IsSubPathOf(fs.DirectoryInfo.New("/a/b/c/d")).Should().BeFalse();
31+
fs.DirectoryInfo.New("/a/b/c/d/e/f").IsSubPathOf(fs.DirectoryInfo.New("/a/b/C/d")).Should().BeFalse();
32+
}
33+
else
34+
{
35+
fs.DirectoryInfo.New("/a/b/C/d/e/f").IsSubPathOf(fs.DirectoryInfo.New("/a/b/c/d")).Should().BeTrue();
36+
fs.DirectoryInfo.New("/a/b/c/d/e/f").IsSubPathOf(fs.DirectoryInfo.New("/a/b/C/d")).Should().BeTrue();
37+
}
38+
}
39+
40+
[Fact]
41+
public void HasParentTests()
42+
{
43+
var fs = new MockFileSystem();
44+
45+
fs.DirectoryInfo.New("/a/b/c/d").HasParent("c").Should().BeTrue();
46+
fs.DirectoryInfo.New("/a/b/c/d/e").HasParent("e").Should().BeTrue();
47+
48+
var caseSensitive = IDirectoryInfoExtensions.IsCaseSensitiveFileSystem;
49+
50+
if (caseSensitive)
51+
fs.DirectoryInfo.New("/a/b/C/d").HasParent("c").Should().BeFalse();
52+
else
53+
fs.DirectoryInfo.New("/a/b/C/d").HasParent("c").Should().BeTrue();
54+
}
55+
}

0 commit comments

Comments
 (0)