Fix enumerating the root directory. (dotnet/corefx#27223)
authorJeremy Kuhne <jeremy.kuhne@microsoft.com>
Sat, 17 Feb 2018 05:52:07 +0000 (21:52 -0800)
committerGitHub <noreply@github.com>
Sat, 17 Feb 2018 05:52:07 +0000 (21:52 -0800)
* Fix enumerating the root directory.

Shouldn't trim the trailing separator when at the root. On Windows that makes
the path drive relative- which breaks most of the logic.

Add a test to catch this case.

* Add the Unix part of the fix.

Commit migrated from https://github.com/dotnet/corefx/commit/5b4ce203c563a20053f32f9901ea6b7dc67c8e37

src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs
src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs
src/libraries/System.IO.FileSystem/tests/Enumeration/RootTests.netcoreapp.cs [new file with mode: 0644]
src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj

index 4a0ccb8..4ec505f 100644 (file)
@@ -41,7 +41,7 @@ namespace System.IO.Enumeration
         public FileSystemEnumerator(string directory, EnumerationOptions options = null)
         {
             _originalRootDirectory = directory ?? throw new ArgumentNullException(nameof(directory));
-            _rootDirectory = Path.GetFullPath(directory).TrimEnd(Path.DirectorySeparatorChar);
+            _rootDirectory = PathHelpers.TrimEndingDirectorySeparator(Path.GetFullPath(directory));
             _options = options ?? EnumerationOptions.Default;
 
             // We need to initialize the directory handle up front to ensure
index ad7ca07..0507adb 100644 (file)
@@ -42,7 +42,7 @@ namespace System.IO.Enumeration
         public FileSystemEnumerator(string directory, EnumerationOptions options = null)
         {
             _originalRootDirectory = directory ?? throw new ArgumentNullException(nameof(directory));
-            _rootDirectory = Path.GetFullPath(directory).TrimEnd(Path.DirectorySeparatorChar);
+            _rootDirectory = PathHelpers.TrimEndingDirectorySeparator(Path.GetFullPath(directory));
             _options = options ?? EnumerationOptions.Default;
 
             // We'll only suppress the media insertion prompt on the topmost directory as that is the
diff --git a/src/libraries/System.IO.FileSystem/tests/Enumeration/RootTests.netcoreapp.cs b/src/libraries/System.IO.FileSystem/tests/Enumeration/RootTests.netcoreapp.cs
new file mode 100644 (file)
index 0000000..258c9d7
--- /dev/null
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO.Enumeration;
+using System.Linq;
+using Xunit;
+
+namespace System.IO.Tests.Enumeration
+{
+    public class RootTests
+    {
+        private class DirectoryRecursed : FileSystemEnumerator<string>
+        {
+            public string LastDirectory { get; private set; }
+
+            public DirectoryRecursed(string directory, EnumerationOptions options)
+                : base(directory, options)
+            {
+            }
+
+            protected override string TransformEntry(ref FileSystemEntry entry)
+                => entry.ToFullPath();
+
+            protected override bool ShouldRecurseIntoEntry(ref FileSystemEntry entry)
+            {
+                LastDirectory = new string(entry.Directory); 
+                return false;
+            }
+        }
+
+        [Fact]
+        public void CanRecurseFromRoot()
+        {
+            string root = Path.GetPathRoot(Path.GetTempPath());
+            using (var recursed = new DirectoryRecursed(root, new EnumerationOptions { AttributesToSkip = FileAttributes.System, RecurseSubdirectories = true }))
+            {
+                while (recursed.MoveNext())
+                {
+                    if (recursed.LastDirectory != null)
+                    {
+                        Assert.Equal(root, recursed.LastDirectory);
+                        return;
+                    }
+
+                    // Should not get back a full path without a single separator (C:\foo.txt or /foo.txt)
+                    Assert.Equal(Path.DirectorySeparatorChar, recursed.Current.SingleOrDefault(c => c == Path.DirectorySeparatorChar));
+                }
+
+                Assert.NotNull(recursed.LastDirectory);
+            }
+        }
+    }
+}
index 4bf205f..402489b 100644 (file)
@@ -62,6 +62,7 @@
     <Compile Include="Enumeration\ErrorHandlingTests.netcoreapp.cs" />
     <Compile Include="Enumeration\IncludePredicateTests.netcoreapp.cs" />
     <Compile Include="Enumeration\PatternTransformTests.netcoreapp.cs" />
+    <Compile Include="Enumeration\RootTests.netcoreapp.cs" />
   </ItemGroup>
   <ItemGroup>
     <!-- Rewritten -->