public IReadOnlyDirectory Mount(IDisposableDirectory autoDisposingDirectory, string mountRoot) { IDirectory mountDir; if ((mountRoot == "/" || mountRoot == "") && !autoDisposingDirectory.EnumerateFiles().Any() && !autoDisposingDirectory.EnumerateDirectories().Any()) { mountDir = autoDisposingDirectory; } // ContainsFile checks for directories as well. else if (!autoDisposingDirectory.ContainsFile(mountRoot)) { mountDir = autoDisposingDirectory.OpenDirectory(mountRoot); } else { throw new IOException("Can not mount projection on an non-empty directory or already existing mount point."); } if (this.Parent != null) { throw new InvalidOperationException("Can not mount subtreee of projection."); } var activeDir = mountDir; foreach (var(name, file) in this.ProjectionState) { switch (file) { case DirectoryInfo dirInfo: activeDir.LinkFrom(dirInfo, name); break; case FileInfo fileInfo: activeDir.LinkFrom(fileInfo, name); break; } } Stack <(string, DirectoryProjection)> projectionsToProcess = new(this.Children.Select((kvp) => (kvp.Key, kvp.Value))); while (projectionsToProcess.Count > 0) { var(projectionName, projectionLevel) = projectionsToProcess.Pop(); activeDir = activeDir.OpenDirectory(projectionName); foreach (var(name, file) in projectionLevel.ProjectionState) { switch (file) { case DirectoryInfo dirInfo: activeDir.LinkFrom(dirInfo, name); break; case FileInfo fileInfo: activeDir.LinkFrom(fileInfo, name); break; } } foreach (var(name, childProjection) in projectionLevel.Children) { projectionsToProcess.Push((name, childProjection)); } } return(mountDir.AsReadOnly()); }
public IReadOnlyDirectory Mount(IDisposableDirectory autoDisposingDirectory) => this.Mount(autoDisposingDirectory, "");