Skip to content

Commit ba7197e

Browse files
authored
Merge pull request #96 from Facepunch/fix/path-without-volume
Fix rooted path without volume label regression on Windows
2 parents 083b29d + 86b2af6 commit ba7197e

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/Zio.Tests/FileSystems/TestPhysicalFileSystem.cs

+13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ public void TestFileSystemInvalidDriveLetterOnWindows()
3131
}
3232
}
3333

34+
[SkippableFact]
35+
public void TestRootedPathWithoutDriveOnWindows()
36+
{
37+
Skip.IfNot(IsWindows, "Testing Windows-specific behavior");
38+
39+
var driveLetter = Directory.GetCurrentDirectory()[0];
40+
var fs = new PhysicalFileSystem();
41+
42+
var resolvedPath = fs.ConvertPathFromInternal("/test");
43+
44+
Assert.Equal($"/mnt/{driveLetter}/test", resolvedPath.ToString(), StringComparer.OrdinalIgnoreCase);
45+
}
46+
3447
[Fact]
3548
public void TestWatcher()
3649
{

src/Zio/FileSystems/PhysicalFileSystem.cs

+14-3
Original file line numberDiff line numberDiff line change
@@ -977,9 +977,12 @@ protected override UPath ConvertPathFromInternalImpl(string innerPath)
977977
if (innerPath.StartsWith(@"\\", StringComparison.Ordinal) || innerPath.StartsWith(@"\?", StringComparison.Ordinal))
978978
throw new NotSupportedException($"Path starting with `\\\\` or `\\?` are not supported -> `{innerPath}` ");
979979

980-
var absolutePath = Path.IsPathRooted(innerPath) ? innerPath : Path.GetFullPath(innerPath);
981-
var driveIndex = absolutePath.IndexOf(":\\", StringComparison.Ordinal);
982-
if (driveIndex != 1)
980+
// We want to avoid using Path.GetFullPath unless absolutely necessary,
981+
// because it can change the case of already rooted paths that contain a ~
982+
var absolutePath = HasWindowsVolumeLabel(innerPath) ? innerPath : Path.GetFullPath(innerPath);
983+
984+
// Assert that Path.GetFullPath returned the format we expect
985+
if (!HasWindowsVolumeLabel(absolutePath))
983986
throw new ArgumentException($"Expecting a drive for the path `{absolutePath}`");
984987

985988
var builder = UPath.GetSharedStringBuilder();
@@ -1032,4 +1035,12 @@ private static bool IsDriveLetter(char c)
10321035
{
10331036
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
10341037
}
1038+
1039+
private static bool HasWindowsVolumeLabel( string path )
1040+
{
1041+
if ( !IsOnWindows )
1042+
throw new NotSupportedException( $"{nameof( HasWindowsVolumeLabel )} is only supported on Windows platforms." );
1043+
1044+
return path.Length >= 3 && path[1] == ':' && path[2] is '\\' or '/';
1045+
}
10351046
}

0 commit comments

Comments
 (0)