diff --git a/Helpers/EDA/DCP.cs b/Helpers/EDA/DCP.cs index 89d6859..656f256 100644 --- a/Helpers/EDA/DCP.cs +++ b/Helpers/EDA/DCP.cs @@ -223,6 +223,7 @@ public class DCP level += 1; foreach (dynamic entry in expandoObject) { +#pragma warning disable IL2026, IL3050 if (entry.Value is ExpandoObject) TextResolveEntry(result, entry.Value, level, string.Concat(super, " : ", entry.Key), i, group); else @@ -262,6 +263,7 @@ public class DCP i = null; } } +#pragma warning restore IL2026, IL3050 } level -= 1; if (level == 0) @@ -273,6 +275,7 @@ public class DCP StringBuilder result = new(); if (result.Length > 0) //Skipping because System.Text.Json changed the way Expando works { +#pragma warning disable IL2026, IL3050 string title = string.Concat(Path.GetFileName(edaObjectFile), " - ", common.Source); dynamic? expandoObject = JsonSerializer.Deserialize(json); _ = result.AppendLine(title); @@ -288,6 +291,7 @@ public class DCP _ = result.AppendLine(edaObjectFile); _ = result.AppendLine(); TextResolveEntry(result, expandoObject, 0, string.Empty, null, group: true); +#pragma warning restore IL2026, IL3050 } return result.ToString(); } diff --git a/Helpers/HelperCompass.cs b/Helpers/HelperCompass.cs index 9c70421..ae0e0e1 100644 --- a/Helpers/HelperCompass.cs +++ b/Helpers/HelperCompass.cs @@ -5,7 +5,7 @@ using System.Text; namespace File_Watcher.Helpers; -internal static partial class HelperCompass +internal class HelperCompass { private static bool _FirstRun = true; @@ -114,7 +114,7 @@ internal static partial class HelperCompass if (!Directory.Exists(directory)) _ = Directory.CreateDirectory(directory); files = GetFiles(appSettings, directory); - logger.LogDebug("Found {Files}", files); + logger.LogDebug("Found {Files} file(s)", files.Count); CopyFiles(appSettings, files); } return true; diff --git a/Helpers/HelperEDADatabase.cs b/Helpers/HelperEDADatabase.cs index 69edd55..6d4f572 100644 --- a/Helpers/HelperEDADatabase.cs +++ b/Helpers/HelperEDADatabase.cs @@ -35,8 +35,10 @@ internal static partial class HelperEDADatabase { Stream stream = ToStream(@this.Trim()); XmlReader? reader = XmlReader.Create(stream, new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document }); +#pragma warning disable IL2026, IL2090 XmlSerializer xmlSerializer = new(typeof(T), typeof(T).GetNestedTypes()); result = xmlSerializer.Deserialize(reader); +#pragma warning restore IL2026, IL2090 stream.Dispose(); } catch (Exception) @@ -131,7 +133,9 @@ internal static partial class HelperEDADatabase continue; // cSpell:enable common.Update(configuration); +#pragma warning disable IL2026, IL3050 json = JsonSerializer.Serialize(configuration, configuration.GetType(), jsonSerializerOptions); +#pragma warning restore IL2026, IL3050 if (common?.UnitName is null) continue; fileName = string.Concat(edaObjectFile.Replace(replace, "Partial"), ".csv"); @@ -211,7 +215,9 @@ internal static partial class HelperEDADatabase List row; StringBuilder sql = new(); string objectTypeDirectory; +#pragma warning disable IL3050 Array objectTypes = Enum.GetValues(typeof(ModuleInstanceTypeName)); +#pragma warning restore IL3050 Dictionary>>> rows = []; string decrypted = RijndaelEncryption.Decrypt(appSettings.EDADatabaseConfiguration.Password, appSettings.Company); string connectionString = $"Data Source={appSettings.EDADatabaseConfiguration.TNS}; User Id={appSettings.EDADatabaseConfiguration.UserName}; Password={decrypted};"; diff --git a/Helpers/HelperNuget.cs b/Helpers/HelperNuget.cs new file mode 100644 index 0000000..2ae4754 --- /dev/null +++ b/Helpers/HelperNuget.cs @@ -0,0 +1,152 @@ +using File_Watcher.Models; +using System.IO.Compression; + +namespace File_Watcher.Helpers; + +internal class HelperNuget +{ + + private static DateTimeOffset? GetDateTimeOffset(string keyFileExtension, FileInfo fileInfo, FileInfo extractKeyFileInfo) + { + DateTimeOffset? dateTimeOffset = null; + using ZipArchive zip = ZipFile.Open(fileInfo.FullName, ZipArchiveMode.Read); + foreach (ZipArchiveEntry zipArchiveEntry in zip.Entries) + { + if (!zipArchiveEntry.Name.EndsWith(keyFileExtension)) + continue; + dateTimeOffset = zipArchiveEntry.LastWriteTime; + if (fileInfo.FullName[0] != '\\') + { + zipArchiveEntry.ExtractToFile(extractKeyFileInfo.FullName); + File.SetCreationTime(extractKeyFileInfo.FullName, fileInfo.CreationTime); + File.SetLastWriteTime(extractKeyFileInfo.FullName, dateTimeOffset.Value.LocalDateTime); + } + break; + } + return dateTimeOffset; + } + + private static bool ExtractKeyFileAndSetDateFromZipEntry(ILogger logger, string[] zipFiles, string keyFileExtension, string keyFileExtensionB, string keyFileExtensionC, bool renameToLower) + { + bool result = false; + string[] files; + string checkFile; + string? lowerName; + FileInfo fileInfo; + FileInfo extractKeyFileInfo; + DateTimeOffset? dateTimeOffset; + foreach (string zipFile in zipFiles) + { + fileInfo = new(zipFile); + if (fileInfo.DirectoryName is null) + throw new NullReferenceException(nameof(fileInfo.DirectoryName)); + lowerName = !renameToLower ? null : Path.Combine(fileInfo.DirectoryName, fileInfo.Name.ToLower()); + if (renameToLower && lowerName is not null && lowerName != fileInfo.FullName) + { + files = Directory.GetFiles(fileInfo.DirectoryName, $"{Path.GetFileNameWithoutExtension(fileInfo.Name)}*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + File.Move(file, Path.Combine(fileInfo.DirectoryName, Path.GetFileName(file).ToLower())); + fileInfo = new(lowerName); + if (fileInfo.DirectoryName is null) + throw new NullReferenceException(nameof(fileInfo.DirectoryName)); + } + extractKeyFileInfo = new(Path.Combine(fileInfo.DirectoryName, $"{Path.GetFileNameWithoutExtension(fileInfo.Name)}{keyFileExtension}")); + if (extractKeyFileInfo.Exists) + { + if (extractKeyFileInfo.CreationTime.ToString("yyyy-MM-dd") == fileInfo.CreationTime.ToString("yyyy-MM-dd") && extractKeyFileInfo.LastWriteTime.ToString("yyyy-MM-dd") == fileInfo.LastWriteTime.ToString("yyyy-MM-dd")) + continue; + File.Delete(extractKeyFileInfo.FullName); + } + try + { + dateTimeOffset = GetDateTimeOffset(keyFileExtension, fileInfo, extractKeyFileInfo); + if (dateTimeOffset is null) + continue; + if (fileInfo.LastWriteTime != dateTimeOffset.Value.LocalDateTime) + { + File.SetLastWriteTime(fileInfo.FullName, dateTimeOffset.Value.LocalDateTime); + if (!result) + result = true; + } + if (string.IsNullOrEmpty(keyFileExtensionB)) + continue; + files = Directory.GetFiles(fileInfo.DirectoryName, keyFileExtensionB, SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + fileInfo = new(file); + if (fileInfo.LastWriteTime != dateTimeOffset.Value.LocalDateTime) + { + File.SetLastWriteTime(fileInfo.FullName, dateTimeOffset.Value.LocalDateTime); + if (!result) + result = true; + } + } + if (string.IsNullOrEmpty(keyFileExtensionC)) + continue; + if (fileInfo.DirectoryName is null) + throw new NullReferenceException(nameof(fileInfo.DirectoryName)); + files = Directory.GetFiles(fileInfo.DirectoryName, keyFileExtensionC, SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + fileInfo = new(file); + if (fileInfo.LastWriteTime != dateTimeOffset.Value.LocalDateTime) + { + File.SetLastWriteTime(fileInfo.FullName, dateTimeOffset.Value.LocalDateTime); + if (!result) + result = true; + } + } + } + catch (Exception) + { + logger.LogInformation("<{zipFile}> is invalid!", zipFile); + checkFile = string.Concat(zipFile, ".err"); + for (int e = 0; e < short.MaxValue; e++) + { + if (!File.Exists(checkFile)) + break; + checkFile = string.Concat(checkFile, e); + } + try + { File.Move(zipFile, checkFile); } + catch (Exception) { logger.LogInformation("<{zipFile}> couldn't be moved!", zipFile); } + } + } + return result; + } + + private static int CopyFiles(NugetConfiguration nugetConfiguration, string[] files) + { + int results = 0; + FileInfo fileInfo; + FileInfo checkFileInfo; + foreach (string file in files) + { + fileInfo = new(file); + checkFileInfo = new(Path.Combine(nugetConfiguration.Destination, fileInfo.Name)); + if (!checkFileInfo.Exists || fileInfo.LastWriteTime != checkFileInfo.LastWriteTime || fileInfo.Length != checkFileInfo.Length) + { + File.Copy(fileInfo.FullName, checkFileInfo.FullName, overwrite: true); + results++; + } + } + return results; + } + + internal static bool Sync(AppSettings appSettings, ILogger logger) + { + NugetConfiguration nugetConfiguration = appSettings.NugetConfiguration; + if (!Directory.Exists(nugetConfiguration.Source)) + _ = Directory.CreateDirectory(nugetConfiguration.Source); + if (!Directory.Exists(nugetConfiguration.Destination)) + _ = Directory.CreateDirectory(nugetConfiguration.Destination); + string[] files = Directory.GetFiles(nugetConfiguration.Source, nugetConfiguration.SearchPattern, SearchOption.AllDirectories); + logger.LogInformation("Found {Files} file(s)", files.Length); + _ = ExtractKeyFileAndSetDateFromZipEntry(logger, files, nugetConfiguration.KeyFileExtension, nugetConfiguration.KeyFileExtensionB, nugetConfiguration.KeyFileExtensionC, nugetConfiguration.RenameToLower); + logger.LogInformation("{Files} file(s) verified", files.Length); + int filesCopied = CopyFiles(nugetConfiguration, files); + logger.LogInformation("Copied {FilesCopied} file(s)", filesCopied); + return true; + } + +} \ No newline at end of file diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs index 10fed8b..2c69925 100644 --- a/Models/AppSettings.cs +++ b/Models/AppSettings.cs @@ -8,6 +8,7 @@ public record AppSettings(EAFLogConfiguration EAFLogConfiguration, EDADatabaseConfiguration EDADatabaseConfiguration, CompassConfiguration CompassConfiguration, DriveConfiguration DriveConfiguration, + NugetConfiguration NugetConfiguration, MetrologyConfiguration MetrologyConfiguration, SerialConfiguration SerialConfiguration, StratusConfiguration StratusConfiguration, diff --git a/Models/Binder/AppSettings.cs b/Models/Binder/AppSettings.cs index f3d9062..8ce39f5 100644 --- a/Models/Binder/AppSettings.cs +++ b/Models/Binder/AppSettings.cs @@ -46,6 +46,7 @@ public class AppSettings Models.EAFLogConfiguration eafLogConfiguration, Models.EAFProgramDataConfiguration eafProgramDataConfiguration, Models.EDADatabaseConfiguration edaDatabaseConfiguration, + Models.NugetConfiguration nugetConfiguration, Models.MetrologyConfiguration metrologyConfiguration, Models.SerialConfiguration serialConfiguration, Models.StratusConfiguration stratusConfiguration, @@ -66,6 +67,7 @@ public class AppSettings edaDatabaseConfiguration, compassConfiguration, driveConfiguration, + nugetConfiguration, metrologyConfiguration, serialConfiguration, stratusConfiguration, @@ -86,6 +88,7 @@ public class AppSettings Models.EAFLogConfiguration eafLogConfiguration, Models.EAFProgramDataConfiguration eafProgramDataConfiguration, Models.EDADatabaseConfiguration edaDatabaseConfiguration, + Models.NugetConfiguration nugetConfiguration, Models.MetrologyConfiguration metrologyConfiguration, Models.SerialConfiguration serialConfiguration, Models.StratusConfiguration stratusConfiguration, @@ -103,6 +106,7 @@ public class AppSettings eafLogConfiguration, eafProgramDataConfiguration, edaDatabaseConfiguration, + nugetConfiguration, metrologyConfiguration, serialConfiguration, stratusConfiguration, diff --git a/Models/Binder/NugetConfiguration.cs b/Models/Binder/NugetConfiguration.cs new file mode 100644 index 0000000..4836aa3 --- /dev/null +++ b/Models/Binder/NugetConfiguration.cs @@ -0,0 +1,84 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models.Binder; + +public class NugetConfiguration +{ + + public string? Destination { get; set; } + public string? KeyFileExtension { get; set; } + public string? KeyFileExtensionB { get; set; } + public string? KeyFileExtensionC { get; set; } + public bool? RenameToLower { get; set; } + public string? SearchPattern { get; set; } + public string? Source { get; set; } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, BinderNugetConfigurationSourceGenerationContext.Default.NugetConfiguration); + return result; + } + + private static void PreVerify(IConfigurationRoot configurationRoot, NugetConfiguration? configuration) + { + if (configuration?.Destination is null) + { + List paths = []; + foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers) + { + if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider) + continue; + if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider) + continue; + paths.Add(physicalFileProvider.Root); + } + throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}"); + } + } + + private static void Verify(NugetConfiguration _) + { + } + + private static Models.NugetConfiguration Get(NugetConfiguration? configuration) + { + Models.NugetConfiguration result; + if (configuration is null) throw new NullReferenceException(nameof(configuration)); + if (configuration.Destination is null) throw new NullReferenceException(nameof(configuration.Destination)); + if (configuration.KeyFileExtension is null) throw new NullReferenceException(nameof(configuration.KeyFileExtension)); + if (configuration.KeyFileExtensionB is null) throw new NullReferenceException(nameof(configuration.KeyFileExtensionB)); + if (configuration.KeyFileExtensionC is null) throw new NullReferenceException(nameof(configuration.KeyFileExtensionC)); + if (configuration.RenameToLower is null) throw new NullReferenceException(nameof(configuration.RenameToLower)); + if (configuration.SearchPattern is null) throw new NullReferenceException(nameof(configuration.SearchPattern)); + if (configuration.Source is null) throw new NullReferenceException(nameof(configuration.Source)); + Verify(configuration); + result = new(configuration.Destination, + configuration.KeyFileExtension, + configuration.KeyFileExtensionB, + configuration.KeyFileExtensionC, + configuration.RenameToLower.Value, + configuration.SearchPattern, + configuration.Source); + return result; + } + + public static Models.NugetConfiguration Get(IConfigurationRoot configurationRoot) + { + Models.NugetConfiguration result; + IConfigurationSection configurationSection = configurationRoot.GetSection(nameof(Models.NugetConfiguration)); +#pragma warning disable IL3050, IL2026 + NugetConfiguration? configuration = configurationSection.Get(); +#pragma warning restore IL3050, IL2026 + PreVerify(configurationRoot, configuration); + result = Get(configuration); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(NugetConfiguration))] +internal partial class BinderNugetConfigurationSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Models/NugetConfiguration.cs b/Models/NugetConfiguration.cs new file mode 100644 index 0000000..e35f9ec --- /dev/null +++ b/Models/NugetConfiguration.cs @@ -0,0 +1,27 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record NugetConfiguration(string Destination, + string KeyFileExtension, + string KeyFileExtensionB, + string KeyFileExtensionC, + bool RenameToLower, + string SearchPattern, + string Source) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, NugetConfigurationSourceGenerationContext.Default.NugetConfiguration); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(NugetConfiguration))] +internal partial class NugetConfigurationSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 45a5af6..c0feb2b 100644 --- a/Program.cs +++ b/Program.cs @@ -22,6 +22,7 @@ public class Program StratusConfiguration stratusConfiguration = Models.Binder.StratusConfiguration.Get(webApplicationBuilder.Configuration); CompassConfiguration compassConfiguration = Models.Binder.CompassConfiguration.Get(webApplicationBuilder.Configuration); MetrologyConfiguration metrologyConfiguration = Models.Binder.MetrologyConfiguration.Get(webApplicationBuilder.Configuration); + NugetConfiguration nugetConfiguration = Models.Binder.NugetConfiguration.Get(webApplicationBuilder.Configuration); WaferCounterConfiguration waferCounterConfiguration = Models.Binder.WaferCounterConfiguration.Get(webApplicationBuilder.Configuration); TransmissionControlProtocolConfiguration transmissionControlProtocolConfiguration = Models.Binder.TransmissionControlProtocolConfiguration.Get(webApplicationBuilder.Configuration); AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration, @@ -30,6 +31,7 @@ public class Program eafLogConfiguration, eafProgramDataConfiguration, edaDatabaseConfiguration, + nugetConfiguration, metrologyConfiguration, serialConfiguration, stratusConfiguration, diff --git a/Worker.cs b/Worker.cs index 0df6e14..45eda4f 100644 --- a/Worker.cs +++ b/Worker.cs @@ -31,6 +31,7 @@ public partial class Worker : BackgroundService { _ = _AppSettings.Helper switch { + nameof(Helpers.HelperNuget) => Helpers.HelperNuget.Sync(_AppSettings, _Logger), nameof(Helpers.HelperTCP) => Helpers.HelperTCP.ReadWrite(_AppSettings, _Logger), nameof(Helpers.HelperCompass) => Helpers.HelperCompass.CopyFile(_AppSettings, _Logger), nameof(Helpers.HelperStratus) => Helpers.HelperStratus.MoveFile(_AppSettings, _Logger),