Example #1
0
        /// <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);
                }
            }
        }