Skip to content

Commit

Permalink
Merge pull request #96 from Facepunch/fix/path-without-volume
Browse files Browse the repository at this point in the history
Fix rooted path without volume label regression on Windows
  • Loading branch information
xoofx authored Aug 1, 2024
2 parents 083b29d + 86b2af6 commit ba7197e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
13 changes: 13 additions & 0 deletions src/Zio.Tests/FileSystems/TestPhysicalFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ public void TestFileSystemInvalidDriveLetterOnWindows()
}
}

[SkippableFact]
public void TestRootedPathWithoutDriveOnWindows()
{
Skip.IfNot(IsWindows, "Testing Windows-specific behavior");

var driveLetter = Directory.GetCurrentDirectory()[0];
var fs = new PhysicalFileSystem();

var resolvedPath = fs.ConvertPathFromInternal("/test");

Assert.Equal($"/mnt/{driveLetter}/test", resolvedPath.ToString(), StringComparer.OrdinalIgnoreCase);
}

[Fact]
public void TestWatcher()
{
Expand Down
17 changes: 14 additions & 3 deletions src/Zio/FileSystems/PhysicalFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -977,9 +977,12 @@ protected override UPath ConvertPathFromInternalImpl(string innerPath)
if (innerPath.StartsWith(@"\\", StringComparison.Ordinal) || innerPath.StartsWith(@"\?", StringComparison.Ordinal))
throw new NotSupportedException($"Path starting with `\\\\` or `\\?` are not supported -> `{innerPath}` ");

var absolutePath = Path.IsPathRooted(innerPath) ? innerPath : Path.GetFullPath(innerPath);
var driveIndex = absolutePath.IndexOf(":\\", StringComparison.Ordinal);
if (driveIndex != 1)
// We want to avoid using Path.GetFullPath unless absolutely necessary,
// because it can change the case of already rooted paths that contain a ~
var absolutePath = HasWindowsVolumeLabel(innerPath) ? innerPath : Path.GetFullPath(innerPath);

// Assert that Path.GetFullPath returned the format we expect
if (!HasWindowsVolumeLabel(absolutePath))
throw new ArgumentException($"Expecting a drive for the path `{absolutePath}`");

var builder = UPath.GetSharedStringBuilder();
Expand Down Expand Up @@ -1032,4 +1035,12 @@ private static bool IsDriveLetter(char c)
{
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}

private static bool HasWindowsVolumeLabel( string path )
{
if ( !IsOnWindows )
throw new NotSupportedException( $"{nameof( HasWindowsVolumeLabel )} is only supported on Windows platforms." );

return path.Length >= 3 && path[1] == ':' && path[2] is '\\' or '/';
}
}

0 comments on commit ba7197e

Please sign in to comment.