clean up pdb files on client, hash assembly file names

This commit is contained in:
Shaun Walker 2022-09-14 10:09:50 -04:00
parent c0f4069a9b
commit 45df729711
3 changed files with 115 additions and 93 deletions

View File

@ -117,6 +117,7 @@ namespace Oqtane.Client
try
{
await interop.RemoveIndexedDBItem(file);
await interop.RemoveIndexedDBItem(file.Replace(".dll", ".pdb"));
}
catch
{

View File

@ -127,7 +127,10 @@ public static class MauiProgram
{
try
{
File.Delete(Path.Combine(folder, file));
foreach (var path in Directory.EnumerateFiles(folder, Path.GetFileNameWithoutExtension(file) + ".*"))
{
File.Delete(path);
}
}
catch
{
@ -159,11 +162,6 @@ public static class MauiProgram
// save assembly to local folder
try
{
int subfolder = entry.FullName.IndexOf('/');
if (subfolder != -1 && !Directory.Exists(Path.Combine(folder, entry.FullName.Substring(0, subfolder))))
{
Directory.CreateDirectory(Path.Combine(folder, entry.FullName.Substring(0, subfolder)));
}
using var stream = File.Create(Path.Combine(folder, entry.FullName));
stream.Write(file, 0, file.Length);
}

View File

@ -103,10 +103,7 @@ namespace Oqtane.Controllers
[HttpGet("list")]
public List<string> List()
{
return _cache.GetOrCreate("assemblieslist", entry =>
{
return GetAssemblyList();
});
return GetAssemblyList().Select(item => item.HashedName).ToList();
}
// GET api/<controller>/load?list=x,y
@ -116,81 +113,90 @@ namespace Oqtane.Controllers
return File(GetAssemblies(list), System.Net.Mime.MediaTypeNames.Application.Octet, "oqtane.dll");
}
private List<string> GetAssemblyList()
private List<ClientAssembly> GetAssemblyList()
{
// get list of assemblies which should be downloaded to client
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
var list = assemblies.Select(a => a.GetName().Name).ToList();
// include version numbers
for (int i = 0; i < list.Count; i++)
return _cache.GetOrCreate("assemblieslist", entry =>
{
list[i] = Path.GetFileName(AddFileDate(Path.Combine(binFolder, list[i] + ".dll")));
}
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var assemblyList = new List<ClientAssembly>();
// insert satellite assemblies at beginning of list
foreach (var culture in _localizationManager.GetInstalledCultures())
{
var assembliesFolderPath = Path.Combine(binFolder, culture);
if (culture == Constants.DefaultCulture)
// get list of assemblies which should be downloaded to client
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
var list = assemblies.Select(a => a.GetName().Name).ToList();
// populate assemblies
for (int i = 0; i < list.Count; i++)
{
continue;
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, list[i] + ".dll")));
}
if (Directory.Exists(assembliesFolderPath))
// insert satellite assemblies at beginning of list
foreach (var culture in _localizationManager.GetInstalledCultures())
{
foreach (var resourceFile in Directory.EnumerateFiles(assembliesFolderPath))
var assembliesFolderPath = Path.Combine(binFolder, culture);
if (culture == Constants.DefaultCulture)
{
list.Insert(0, culture + "/" + Path.GetFileName(AddFileDate(resourceFile)));
continue;
}
if (Directory.Exists(assembliesFolderPath))
{
foreach (var resourceFile in Directory.EnumerateFiles(assembliesFolderPath))
{
assemblyList.Insert(0, new ClientAssembly(resourceFile));
}
}
else
{
_filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
}
}
else
{
_filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
}
}
// insert module and theme dependencies at beginning of list
foreach (var assembly in assemblies)
{
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModule))))
// insert module and theme dependencies at beginning of list
foreach (var assembly in assemblies)
{
var instance = Activator.CreateInstance(type) as IModule;
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModule))))
{
var path = Path.Combine(binFolder, name + ".dll");
if (System.IO.File.Exists(path))
var instance = Activator.CreateInstance(type) as IModule;
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
{
path = Path.GetFileName(AddFileDate(path));
if (!list.Contains(path)) list.Insert(0, path);
var filepath = Path.Combine(binFolder, name + ".dll");
if (System.IO.File.Exists(filepath))
{
if (!assemblyList.Exists(item => item.FilePath == filepath))
{
assemblyList.Insert(0, new ClientAssembly(filepath));
}
}
else
{
_filelogger.LogError(Utilities.LogMessage(this, $"Module {instance.ModuleDefinition.ModuleDefinitionName} Dependency {name}.dll Does Not Exist"));
}
}
else
}
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))))
{
var instance = Activator.CreateInstance(type) as ITheme;
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
{
_filelogger.LogError(Utilities.LogMessage(this, $"Module {instance.ModuleDefinition.ModuleDefinitionName} Dependency {name}.dll Does Not Exist"));
var filepath = Path.Combine(binFolder, name + ".dll");
if (System.IO.File.Exists(filepath))
{
if (!assemblyList.Exists(item => item.FilePath == filepath))
{
assemblyList.Insert(0, new ClientAssembly(filepath));
}
}
else
{
_filelogger.LogError(Utilities.LogMessage(this, $"Theme {instance.Theme.ThemeName} Dependency {name}.dll Does Not Exist"));
}
}
}
}
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))))
{
var instance = Activator.CreateInstance(type) as ITheme;
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
var path = Path.Combine(binFolder, name + ".dll");
if (System.IO.File.Exists(path))
{
path = Path.GetFileName(AddFileDate(path));
if (!list.Contains(path)) list.Insert(0, path);
}
else
{
_filelogger.LogError(Utilities.LogMessage(this, $"Theme {instance.Theme.ThemeName} Dependency {name}.dll Does Not Exist"));
}
}
}
}
return list;
return assemblyList;
});
}
private byte[] GetAssemblies(string list)
@ -213,14 +219,11 @@ namespace Oqtane.Controllers
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
// get list of assemblies which should be downloaded to client
List<string> assemblies;
if (list == "*")
List<ClientAssembly> assemblies = GetAssemblyList();
if (list != "*")
{
assemblies = GetAssemblyList();
}
else
{
assemblies = list.Split(',').ToList();
var filter = list.Split(',').ToList();
assemblies.RemoveAll(item => !filter.Contains(item.HashedName));
}
// create zip file containing assemblies and debug symbols
@ -228,22 +231,21 @@ namespace Oqtane.Controllers
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (string file in assemblies)
foreach (var assembly in assemblies)
{
var filename = RemoveFileDate(file);
if (System.IO.File.Exists(Path.Combine(binFolder, filename)))
if (System.IO.File.Exists(assembly.FilePath))
{
using (var filestream = new FileStream(Path.Combine(binFolder, filename), FileMode.Open, FileAccess.Read))
using (var entrystream = archive.CreateEntry(file).Open())
using (var filestream = new FileStream(assembly.FilePath, FileMode.Open, FileAccess.Read))
using (var entrystream = archive.CreateEntry(assembly.HashedName).Open())
{
filestream.CopyTo(entrystream);
}
}
filename = filename.Replace(".dll", ".pdb");
if (System.IO.File.Exists(Path.Combine(binFolder, filename)))
var pdb = assembly.FilePath.Replace(".dll", ".pdb");
if (System.IO.File.Exists(pdb))
{
using (var filestream = new FileStream(Path.Combine(binFolder, filename), FileMode.Open, FileAccess.Read))
using (var entrystream = archive.CreateEntry(file.Replace(".dll", ".pdb")).Open())
using (var filestream = new FileStream(pdb, FileMode.Open, FileAccess.Read))
using (var entrystream = archive.CreateEntry(assembly.HashedName.Replace(".dll", ".pdb")).Open())
{
filestream.CopyTo(entrystream);
}
@ -255,18 +257,6 @@ namespace Oqtane.Controllers
}
}
private string AddFileDate(string filepath)
{
DateTime lastwritetime = System.IO.File.GetLastWriteTime(filepath);
return Path.GetFileNameWithoutExtension(filepath) + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
}
private string RemoveFileDate(string filepath)
{
var segments = filepath.Split(".");
return string.Join(".", segments, 0, segments.Length - 2) + Path.GetExtension(filepath);
}
private async Task RegisterContact(string email)
{
try
@ -292,5 +282,38 @@ namespace Oqtane.Controllers
{
await RegisterContact(email);
}
public struct ClientAssembly
{
public ClientAssembly(string filepath)
{
FilePath = filepath;
DateTime lastwritetime = System.IO.File.GetLastWriteTime(filepath);
HashedName = GetDeterministicHashCode(filepath).ToString("X8") + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
}
public string FilePath { get; private set; }
public string HashedName { get; private set; }
}
private static int GetDeterministicHashCode(string value)
{
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < value.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ value[i];
if (i == value.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
}
return hash1 + (hash2 * 1566083941);
}
}
}
}