Skip to content

Commit 622e791

Browse files
authored
Merge pull request #62 from rameel/fix-prefix-path-resolution
PrefixedFileSystem: Forward all paths unchanged when prefix is "/"
2 parents 96c04d4 + 313211b commit 622e791

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

src/Ramstack.FileSystem.Prefixed/PrefixedFileSystem.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,15 @@ internal string WrapWithPrefix(string underlyingPath)
113113
{
114114
Debug.Assert(VirtualPath.IsNormalized(path));
115115

116+
if (prefix == "/")
117+
return path;
118+
116119
if (path == prefix)
117120
return "/";
118121

119-
if (path.StartsWith(prefix, StringComparison.Ordinal) && path[prefix.Length] == '/')
120-
return new string(path.AsSpan(prefix.Length));
122+
if ((uint)prefix.Length < (uint)path.Length)
123+
if (path.StartsWith(prefix, StringComparison.Ordinal) && path[prefix.Length] == '/')
124+
return new string(path.AsSpan(prefix.Length));
121125

122126
return null;
123127
}

tests/Ramstack.FileSystem.Prefixed.Tests/PrefixedFileSystemTests.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Reflection;
2+
13
using Ramstack.FileSystem.Physical;
24
using Ramstack.FileSystem.Specification.Tests;
35
using Ramstack.FileSystem.Specification.Tests.Utilities;
@@ -7,8 +9,59 @@ namespace Ramstack.FileSystem.Prefixed;
79
[TestFixture]
810
public class PrefixedFileSystemTests : VirtualFileSystemSpecificationTests
911
{
12+
private static readonly Func<string, string, string?> s_unwrapPrefix =
13+
typeof(PrefixedFileSystem)
14+
.GetMethod("TryUnwrapPrefix", BindingFlags.Static | BindingFlags.NonPublic)!
15+
.CreateDelegate<Func<string, string, string?>>();
16+
1017
private readonly TempFileStorage _storage = new TempFileStorage();
1118

19+
[TestCase("/", "/", ExpectedResult = "/")]
20+
[TestCase("/", "/foo", ExpectedResult = "/foo")]
21+
[TestCase("/", "/a/b/c", ExpectedResult = "/a/b/c")]
22+
23+
[TestCase("/a/b", "/a/b", ExpectedResult = "/")]
24+
25+
[TestCase("/a/b", "/a/b/c", ExpectedResult = "/c")]
26+
[TestCase("/a/b", "/a/b/c/d", ExpectedResult = "/c/d")]
27+
28+
[TestCase("/a/b", "/a/bc", ExpectedResult = null)]
29+
30+
[TestCase("/a/b", "/a/c", ExpectedResult = null)]
31+
[TestCase("/a/b", "/a", ExpectedResult = null)]
32+
public string? UnwrapPrefix(string prefix, string path) =>
33+
s_unwrapPrefix(path, prefix);
34+
35+
[Test]
36+
public async Task File_RootPrefix_DelegatesToInnerProvider()
37+
{
38+
using var fs = new PrefixedFileSystem("/",
39+
new PhysicalFileSystem(_storage.Root));
40+
41+
var file = fs.GetFile("/project/README.md");
42+
Assert.That(await file.ExistsAsync(), Is.True);
43+
}
44+
45+
[Test]
46+
public async Task File_RootPrefix_MissingFile_ReturnsNotFound()
47+
{
48+
using var fs = new PrefixedFileSystem("/",
49+
new PhysicalFileSystem(_storage.Root));
50+
51+
var file = fs.GetFile("/project/nonexistent.txt");
52+
Assert.That(await file.ExistsAsync(), Is.False);
53+
}
54+
55+
[Test]
56+
public async Task Directory_RootPrefix_DelegatesToInnerProvider()
57+
{
58+
using var fs = new PrefixedFileSystem("/",
59+
new PhysicalFileSystem(_storage.Root));
60+
61+
var file = fs.GetDirectory("/project");
62+
Assert.That(await file.ExistsAsync(), Is.True);
63+
}
64+
1265
[Test]
1366
public async Task File_Create_InsideArtificialDirectory_ThrowsException()
1467
{

0 commit comments

Comments
 (0)