| File: Mount\Archive\ZipFileMountPoint.cs | Web Access |
| Project: src\sdk\src\TemplateEngine\Microsoft.TemplateEngine.Edge\Microsoft.TemplateEngine.Edge.csproj (Microsoft.TemplateEngine.Edge) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.IO.Compression; using Microsoft.TemplateEngine.Abstractions; using Microsoft.TemplateEngine.Abstractions.Mount; namespace Microsoft.TemplateEngine.Edge.Mount.Archive { /// <summary> /// Mount point implementation for zip file. /// NuGet packages are zip files, so they are handled by this mount point. /// </summary> internal class ZipFileMountPoint : IMountPoint { private IReadOnlyDictionary<string, IFileSystemInfo>? _universe; internal ZipFileMountPoint(IEngineEnvironmentSettings environmentSettings, IMountPoint? parent, string mountPointUri, ZipArchive archive) { MountPointUri = mountPointUri; Parent = parent; EnvironmentSettings = environmentSettings; Archive = archive; Root = new ZipFileDirectory(this, "/", string.Empty); } public IDirectory Root { get; } public IMountPoint? Parent { get; } public string MountPointUri { get; } public IEngineEnvironmentSettings EnvironmentSettings { get; } internal ZipArchive Archive { get; } internal IReadOnlyDictionary<string, IFileSystemInfo> Universe { get { if (_universe == null) { Dictionary<string, IFileSystemInfo> universe = new Dictionary<string, IFileSystemInfo> { ["/"] = Root }; foreach (ZipArchiveEntry entry in Archive.Entries) { string[] parts = entry.FullName.Split('/', '\\'); string path = "/"; IDirectory? parentDir = (IDirectory)universe["/"]; for (int i = 0; parentDir != null && i < parts.Length - 1; ++i) { parts[i] = Uri.UnescapeDataString(parts[i]); path += parts[i] + "/"; if (!universe.TryGetValue(path, out IFileSystemInfo? parentDirEntry)) { universe[path] = parentDirEntry = new ZipFileDirectory(this, path, parts[i]); } //If we mistakenly classified something with children as a file before, reclassify it as a directory if (parentDirEntry is IFile file) { universe[path] = parentDirEntry = new ZipFileDirectory(this, file.FullPath, file.Name); } parentDir = parentDirEntry as IDirectory; } if (parentDir != null && !string.IsNullOrEmpty(entry.Name)) { string unescaped = Uri.UnescapeDataString(entry.Name); path += unescaped; universe[path] = new ZipFileFile(this, path, unescaped, entry); } } _universe = universe; } return _universe; } } internal Guid MountPointFactoryId => ZipFileMountPointFactory.FactoryId; public IFile FileInfo(string path) { return new ZipFileFile(this, path, path.Substring(path.LastIndexOf('/') + 1), null); } public IDirectory? DirectoryInfo(string path) { if (Universe.TryGetValue(path, out IFileSystemInfo info)) { return info as IDirectory; } else if (Universe.TryGetValue(path + "/", out info)) { return info as IDirectory; } return new ZipFileDirectory(this, path, path.Substring(path.LastIndexOf('/') + 1)); } public IFileSystemInfo? FileSystemInfo(string path) { IFile? file = FileInfo(path); if (file != null && file.Exists) { return file; } return DirectoryInfo(path); } public void Dispose() { Archive.Dispose(); } } }