public static async Task <SearchResult <IUnixFileSystemEntry> > SearchEntryAsync(this IUnixFileSystem fileSystem, [NotNull, ItemNotNull] Stack <IUnixDirectoryEntry> currentPath, [NotNull, ItemNotNull] IReadOnlyList <string> pathElements, CancellationToken cancellationToken) { var sourceDir = await GetDirectoryAsync(fileSystem, currentPath, new ListSegment <string>(pathElements, 0, pathElements.Count - 1), cancellationToken); if (sourceDir == null) { return(null); } IUnixFileSystemEntry foundEntry; var fileName = pathElements[pathElements.Count - 1]; switch (fileName) { case "": currentPath.Clear(); fileName = null; foundEntry = fileSystem.Root; break; case ".": if (currentPath.Count != 0) { foundEntry = currentPath.Pop(); fileName = foundEntry.Name; } else { foundEntry = fileSystem.Root; fileName = null; } break; case "..": if (currentPath.Count != 0) { currentPath.Pop(); } if (currentPath.Count != 0) { foundEntry = currentPath.Pop(); fileName = foundEntry.Name; } else { foundEntry = fileSystem.Root; fileName = null; } break; default: foundEntry = await fileSystem.GetEntryByNameAsync(sourceDir, fileName, cancellationToken); break; } return(new SearchResult <IUnixFileSystemEntry>(sourceDir, foundEntry, fileName)); }
public static async Task <SearchResult <IUnixFileEntry> > SearchFileAsync(this IUnixFileSystem fileSystem, [NotNull, ItemNotNull] Stack <IUnixDirectoryEntry> currentPath, [NotNull, ItemNotNull] IReadOnlyList <string> pathElements, CancellationToken cancellationToken) { var sourceDir = await GetDirectoryAsync(fileSystem, currentPath, new ListSegment <string>(pathElements, 0, pathElements.Count - 1), cancellationToken); if (sourceDir == null) { return(null); } var fileName = pathElements[pathElements.Count - 1]; var foundEntry = await fileSystem.GetEntryByNameAsync(sourceDir, fileName, cancellationToken); var foundFileEntry = foundEntry as IUnixFileEntry; if (foundEntry != null && foundFileEntry == null) { return(null); } return(new SearchResult <IUnixFileEntry>(sourceDir, foundFileEntry, fileName)); }
public static async Task <IUnixDirectoryEntry> GetDirectoryAsync([NotNull] this IUnixFileSystem fileSystem, [NotNull, ItemNotNull] Stack <IUnixDirectoryEntry> currentPath, [NotNull, ItemNotNull] IReadOnlyList <string> pathElements, CancellationToken cancellationToken) { IUnixDirectoryEntry currentDir = currentPath.Count == 0 ? fileSystem.Root : currentPath.Peek(); foreach (var pathElement in pathElements) { if (pathElement == string.Empty) { currentDir = fileSystem.Root; currentPath.Clear(); continue; } if (pathElement == ".") { continue; } if (pathElement == "..") { if (currentPath.Count != 0) { currentPath.Pop(); currentDir = currentPath.Count == 0 ? fileSystem.Root : currentPath.Peek(); } continue; } var foundEntry = await fileSystem.GetEntryByNameAsync(currentDir, pathElement, cancellationToken).ConfigureAwait(false); if (!(foundEntry is IUnixDirectoryEntry foundDirEntry)) { return(null); } currentPath.Push(foundDirEntry); currentDir = foundDirEntry; } return(currentDir); }
/// <summary> /// Tries to select the given <paramref name="path"/>. /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="pathEntries">The current path (entries).</param> /// <param name="path">The path to select.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The result of the selection.</returns> public static async Task <PathSelectionResult> SelectAsync( this IUnixFileSystem fileSystem, IEnumerable <IUnixDirectoryEntry> pathEntries, string?path, CancellationToken cancellationToken) { var currentDirectoryEntries = new Stack <IUnixDirectoryEntry>(pathEntries); IUnixDirectoryEntry currentDirectoryEntry; if (currentDirectoryEntries.Count == 0) { currentDirectoryEntry = fileSystem.Root; currentDirectoryEntries.Push(currentDirectoryEntry); } else { currentDirectoryEntry = currentDirectoryEntries.Peek(); } var pathSegments = new PathEnumerator(path) .NormalizePath(GetPathEntryNames(currentDirectoryEntries)) .ToArray(); for (var pathSegmentIndex = 0; pathSegmentIndex != pathSegments.Length; ++pathSegmentIndex) { var pathSegment = pathSegments[pathSegmentIndex]; if (pathSegment == "/") { currentDirectoryEntries.Clear(); currentDirectoryEntry = fileSystem.Root; currentDirectoryEntries.Push(currentDirectoryEntry); continue; } var isDirectoryExpected = pathSegment.EndsWith("/"); var childName = isDirectoryExpected ? pathSegment.Substring(0, pathSegment.Length - 1) : pathSegment; var nextEntry = await fileSystem.GetEntryByNameAsync( currentDirectoryEntry, childName, cancellationToken) .ConfigureAwait(false); if (nextEntry == null) { // Entry not found var missingPathSegments = pathSegments.Skip(pathSegmentIndex).ToArray(); var lastIsDirectory = missingPathSegments[missingPathSegments.Length - 1].EndsWith("/"); if (lastIsDirectory) { return(PathSelectionResult.CreateMissingDirectory( currentDirectoryEntries, missingPathSegments)); } return(PathSelectionResult.CreateMissingFileOrDirectory( currentDirectoryEntries, missingPathSegments)); } var isDirectory = nextEntry is IUnixDirectoryEntry; if (isDirectoryExpected && !isDirectory) { // File instead of directory found var missingPathSegments = pathSegments.Skip(pathSegmentIndex).ToArray(); return(PathSelectionResult.CreateMissingDirectory( currentDirectoryEntries, missingPathSegments)); } if (!isDirectory) { return(PathSelectionResult.Create( currentDirectoryEntries, (IUnixFileEntry)nextEntry)); } currentDirectoryEntry = (IUnixDirectoryEntry)nextEntry; currentDirectoryEntries.Push(currentDirectoryEntry); } // Found directory return(PathSelectionResult.Create( currentDirectoryEntries)); }