/// <inheritdoc /> protected override IEnumerable <UPath> EnumeratePathsImpl(UPath path, string searchPattern, SearchOption searchOption, SearchTarget searchTarget) { // Use the search pattern to normalize the path/search pattern var search = SearchPattern.Parse(ref path, ref searchPattern); var originalSrcPath = path; // Internal method used to retrieve the list of root directories SortedSet <UPath> GetRootDirectories() { var directories = new SortedSet <UPath>(UPath.DefaultComparerIgnoreCase); lock (_mounts) { foreach (var mountName in _mounts.Keys) { directories.Add(mountName); } } if (NextFileSystem != null) { foreach (var dir in NextFileSystem.EnumeratePaths(path, "*", SearchOption.TopDirectoryOnly, SearchTarget.Directory)) { if (!directories.Contains(dir)) { directories.Add(dir); } } } return(directories); } IEnumerable <UPath> EnumeratePathFromFileSystem(UPath subPath, bool failOnInvalidPath) { var fs = TryGetMountOrNext(ref subPath, out var mountPath); if (fs == null) { if (failOnInvalidPath) { throw NewDirectoryNotFoundException(originalSrcPath); } yield break; } if (fs != NextFileSystem) { // In the case of a mount, we need to return the full path Debug.Assert(!mountPath.IsNull); foreach (var entry in fs.EnumeratePaths(subPath, searchPattern, searchOption, searchTarget)) { yield return(mountPath / entry.ToRelative()); } } else { foreach (var entry in fs.EnumeratePaths(subPath, searchPattern, searchOption, searchTarget)) { yield return(entry); } } } // Special case for the root as we have to return the list of mount directories // and merge them with the underlying FileSystem if (path == UPath.Root) { var entries = new SortedSet <UPath>(UPath.DefaultComparerIgnoreCase); // Return the list of dircetories var directories = GetRootDirectories(); // Process the files first if (NextFileSystem != null && (searchTarget == SearchTarget.File || searchTarget == SearchTarget.Both)) { foreach (var file in NextFileSystem.EnumeratePaths(path, searchPattern, SearchOption.TopDirectoryOnly, SearchTarget.File)) { entries.Add(file); } } if (searchTarget != SearchTarget.File) { foreach (var dir in directories) { if (search.Match(dir)) { entries.Add(dir); } } } // Return all entries sorted foreach (var entry in entries) { yield return(entry); } if (searchOption == SearchOption.AllDirectories) { foreach (var dir in directories) { foreach (var entry in EnumeratePathFromFileSystem(dir, false)) { yield return(entry); } } } } else { foreach (var entry in EnumeratePathFromFileSystem(path, true)) { yield return(entry); } } }