|
// 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();
}
}
}
|