From 38e7286ed407d031e0902155319fb827016f1d51 Mon Sep 17 00:00:00 2001 From: Schwirg László Date: Tue, 13 May 2025 09:43:18 +0200 Subject: [PATCH] v 1.34.0 - CompareDirectories funkció beépítése --- Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - CommandLineParser.cs | 12 +++++++++--- Vrh.Log4Pro.MaintenanceConsole/Manager - BackupPackageManager.cs | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- Vrh.Log4Pro.MaintenanceConsole/Properties/AssemblyInfo.cs | 4 ++-- 3 files changed, 181 insertions(+), 7 deletions(-) diff --git a/Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - CommandLineParser.cs b/Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - CommandLineParser.cs index 83dc5c9..013c123 100644 --- a/Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - CommandLineParser.cs +++ b/Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - CommandLineParser.cs @@ -288,12 +288,18 @@ namespace Vrh.Log4Pro.MaintenanceConsole.CommandLineParserNS public static class Functions { public const string CMD_PACKAGES = "-PACKAGES"; - public static class CreateBackupPackage + public const string CMD_DIR1 = "-DIR1"; + public const string CMD_DIR2 = "-DIR2"; + public static class CreateBackupPackage { public const string KEY = "CRE"; } - } - } + public static class CompareDirectories + { + public const string KEY = "COM"; + } + } + } public static class SQLDataBaseManager { public const string KEY = "SQL"; diff --git a/Vrh.Log4Pro.MaintenanceConsole/Manager - BackupPackageManager.cs b/Vrh.Log4Pro.MaintenanceConsole/Manager - BackupPackageManager.cs index fe7faa3..425d4b1 100644 --- a/Vrh.Log4Pro.MaintenanceConsole/Manager - BackupPackageManager.cs +++ b/Vrh.Log4Pro.MaintenanceConsole/Manager - BackupPackageManager.cs @@ -22,6 +22,7 @@ using Vrh.XmlProcessing; using VRH.Common; using System.Xml.Linq; using System.Text.RegularExpressions; +using System.Security.Cryptography; namespace Vrh.Log4Pro.MaintenanceConsole.BackupPackageManagerNS { @@ -42,7 +43,8 @@ namespace Vrh.Log4Pro.MaintenanceConsole.BackupPackageManagerNS var menufunctions = new Menu("Manage Backup Packages", "Select the management function!") .AddMenuItem(new Menu.Item(CLP.Module.BackupPackageManager.Functions.CreateBackupPackage.KEY, "Create backup package", CreateBackupPackage,ep)) - .SetSelectionMode(Menu.SelectionMode.Single) + .AddMenuItem(new Menu.Item(CLP.Module.BackupPackageManager.Functions.CompareDirectories.KEY, "Compare directories", CompareDirectories, ep)) + .SetSelectionMode(Menu.SelectionMode.Single) .SetMenuHeaderDisplayer(BackupPackageListDisplayer); menufunctions.ExecuteMenu(functionkey); return o2; @@ -50,7 +52,173 @@ namespace Vrh.Log4Pro.MaintenanceConsole.BackupPackageManagerNS #endregion Execute #region First level Executors with UI - private static object CreateBackupPackage(object parameter, object o) + internal static object CompareDirectories(object parameter, object o) + { + var config = parameter==null?null:((parameter as Menu.ExecutorParameter).GetConfig()); + var args = parameter == null ? null : ((parameter as Menu.ExecutorParameter).Args); + + var dir1= CommandLine.GetCommandLineArgument(args, CLP.Module.BackupPackageManager.Functions.CMD_DIR1); + var dir2 = CommandLine.GetCommandLineArgument(args, CLP.Module.BackupPackageManager.Functions.CMD_DIR2); + + + string rootWORKING = ColorConsole.ReadLine("Enter path to WORKING INSTALLATION directory:", defaultvalue: dir1 ?? "", required: true); //@"C:\Path\To\Folder1"; + string rootUPGRADE = ColorConsole.ReadLine("Enter path to UPGRADE INSTALLATION directory:", defaultvalue: dir1 ?? "", required: true); //@"C:\Path\To\Folder2"; + string searchpatterncsvlist = ColorConsole.ReadLine("Enter search pattern (csv list):", defaultvalue: "*.dll,*.exe", required: true); //@"C:\Path\To\Folder2"; + + rootWORKING = rootWORKING + @"\"; rootWORKING.Replace(@"/", @"\").Replace(@"\\", @"\"); + rootUPGRADE = rootUPGRADE + @"\"; rootUPGRADE.Replace(@"/", @"\").Replace(@"\\", @"\"); + + ColorConsole.WriteLine("Comparing folders..."); + ColorConsole.WriteLine($" WORKING INSTALLATION: {rootWORKING}"); + ColorConsole.WriteLine($" UPGRADE INSTALLATION: {rootUPGRADE}"); + ColorConsole.WriteLine($" Search patterns: {searchpatterncsvlist}"); + ColorConsole.WriteLine(); + + + var folder1Files = GetFilesWithRelativePaths(rootWORKING, searchpatterncsvlist); + var folder2Files = GetFilesWithRelativePaths(rootUPGRADE, searchpatterncsvlist); + + var allKeys = new HashSet(folder1Files.Keys); + allKeys.UnionWith(folder2Files.Keys); + + var savedcursortop = Console.CursorTop; + Console.WriteLine(); + var actualcursortop = Console.CursorTop; + var numberofprocessedfiles = 0; + var upgradefiles = new Dictionary(); + foreach (var relativePath in allKeys.OrderBy(p => p)) + { + numberofprocessedfiles++; + if (numberofprocessedfiles < 25) + { + actualcursortop = Console.CursorTop; + ColorConsole.SetCursorPosition(0, savedcursortop); ColorConsole.Write(relativePath, suffix: new string(' ', 20)); + ColorConsole.SetCursorPosition(0, actualcursortop); + } + bool inWORKFolder = folder1Files.TryGetValue(relativePath, out string file1); + bool inUPGRADEFolder = folder2Files.TryGetValue(relativePath, out string file2); + + if (inWORKFolder && inUPGRADEFolder) + { + if (!FilesAreEqual(file1, file2, out string difftext)) + { + //ColorConsole.WriteLine($"DIFFERENT ({difftext}): {relativePath}", ConsoleColor.Yellow); + ColorConsole.WriteLine($"< {relativePath} ({difftext}):", ConsoleColor.Yellow); + upgradefiles.Add(relativePath, CompareDirectoriesActions.CopyFROMUPGRADE); + } + } + else if (inWORKFolder) + { + //ColorConsole.WriteLine($"ONLY IN Folder1: {relativePath}", ConsoleColor.Yellow); + ColorConsole.WriteLine($"-- {relativePath}", ConsoleColor.Yellow); + upgradefiles.Add(relativePath, CompareDirectoriesActions.DeleteINWORKING); + } + else if (inUPGRADEFolder) + { + //ColorConsole.WriteLine($"ONLY IN Folder2: {relativePath}", ConsoleColor.Yellow); + ColorConsole.WriteLine($"<< {relativePath}", ConsoleColor.Yellow); + upgradefiles.Add(relativePath, CompareDirectoriesActions.CopyFROMUPGRADE); + } + } + ColorConsole.WriteLine(); + string movefiles = ColorConsole.ReadLine("Do You want to upgrade WORKING INSTALLATION with UPGRADE INSTALLATION:",validitylist: new List{"yes","no","YES","NO", }, defaultvalue: "no", required: true); //@"C:\Path\To\Folder1"; + if (movefiles.ToUpper() == "YES") + { + foreach (var uf in upgradefiles) + { + if (uf.Value == CompareDirectoriesActions.CopyFROMUPGRADE) { File.Copy(Path.Combine(rootUPGRADE, uf.Key), Path.Combine(rootWORKING, uf.Key)); } + else if (uf.Value == CompareDirectoriesActions.DeleteINWORKING) { File.Delete(Path.Combine(rootWORKING,uf.Key)); } + } + } + return o; + } + private enum CompareDirectoriesActions { CopyFROMUPGRADE, DeleteINWORKING,} + private static Dictionary GetFilesWithRelativePaths(string root,string searchpattern="*") + { + var searchpatternlist = searchpattern.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); + List files = new List() { }; + foreach (var sp in searchpatternlist) + { + files.AddRange(Directory.GetFiles(root, sp, SearchOption.AllDirectories)); + } + var dict = new Dictionary(); + foreach (var file in files) + { + string relativePath = GetRelativePath(root, file); + dict[relativePath] = file; + } + return dict; + } + /// + /// Creates a relative path from one file or folder to another. + /// + /// Contains the directory that defines the start of the relative path. + /// Contains the path that defines the endpoint of the relative path. + /// The relative path from the start directory to the end path or toPath if the paths are not related. + /// + /// + /// + public static string GetRelativePath(String fromPath, String toPath) + { + if (String.IsNullOrEmpty(fromPath)) throw new ArgumentNullException("fromPath"); + if (String.IsNullOrEmpty(toPath)) throw new ArgumentNullException("toPath"); + + Uri fromUri = new Uri(fromPath); + Uri toUri = new Uri(toPath); + + if (fromUri.Scheme != toUri.Scheme) { return toPath; } // path can't be made relative. + + Uri relativeUri = fromUri.MakeRelativeUri(toUri); + String relativePath = Uri.UnescapeDataString(relativeUri.ToString()); + + if (toUri.Scheme.Equals("file", StringComparison.InvariantCultureIgnoreCase)) + { + relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + + return relativePath; + } + private static bool FilesAreEqual(string WORKINGfilePath, string UPGRADEfilePath,out string differencetext) + { + differencetext = null; + var fiW = new FileInfo(WORKINGfilePath); + var fiU = new FileInfo(UPGRADEfilePath); + + var fvW = FileVersionInfo.GetVersionInfo(WORKINGfilePath); + var fvU = FileVersionInfo.GetVersionInfo(UPGRADEfilePath); + var fvW1=GetVersionNumber(fvW, out string fvW2); + var fvU1 = GetVersionNumber(fvU, out string fvU2); + var fveresiondifftext = "";// $" {fvW1}<>{fvU1};{fvW2}<>{fvU2}"; + var pvW1 = GetVersionNumber(fvW, out string pvW2,true); + var pvU1 = GetVersionNumber(fvU, out string pvU2,true); + var pveresiondifftext = "";// $" {pvW1}<>{pvU1};{pvW2}<>{pvU2}"; + if (fvW.FileVersion != fvU.FileVersion) { string oldertext = fvW1 > fvU1 ? "DOWNGRADE":"UPGRADE"; differencetext = $"{oldertext} FileVersion: {fveresiondifftext} {fvW.FileVersion} <--> {fvU.FileVersion}"; return false; } + if (fvW.ProductVersion != fvU.ProductVersion) { string oldertext = pvW1 > pvU1 ? "DOWNGRADE" : "UPGRADE"; differencetext = $"{oldertext} ProductVersion: {pveresiondifftext} {fvW.ProductVersion} <--> {fvU.ProductVersion}"; return false; } + //if (fi1.CreationTime != fi2.CreationTime) return false; + //if (fi1.LastWriteTimeUtc != fi2.LastWriteTimeUtc) { differencetext = "LastWriteTimeUTC"; return false; } + if (fiW.Length != fiU.Length) { string oldertext = fiW.Length > fiU.Length?"DOWNSIZE":"UPSIZE"; differencetext = $"Length: {oldertext} {fiW.Length} <--> {fiU.Length}"; return false; } + using (var sha256 = SHA256.Create()) + using (var stream1 = File.OpenRead(WORKINGfilePath)) + using (var stream2 = File.OpenRead(UPGRADEfilePath)) + { + var hash1 = sha256.ComputeHash(stream1); + var hash2 = sha256.ComputeHash(stream2); + + if (!hash1.SequenceEqual(hash2)) { differencetext = "Hash/Content"; return false; } + } + return true; + } + private static long GetVersionNumber(FileVersionInfo vi,out string vt,bool useproductversion=false) + { + vt = useproductversion + ? $"{vi.ProductMajorPart}.{vi.ProductMinorPart}.{vi.ProductBuildPart}.{vi.ProductPrivatePart}" + : $"{vi.FileMajorPart}.{vi.FileMinorPart}.{vi.FileBuildPart}.{vi.FilePrivatePart}"; + long numberbase = 10000; + return useproductversion + ? vi.ProductMajorPart * numberbase * numberbase * numberbase + vi.ProductMinorPart * numberbase * numberbase + vi.ProductBuildPart * numberbase + vi.ProductPrivatePart + : vi.FileMajorPart * numberbase * numberbase * numberbase + vi.FileMinorPart * numberbase * numberbase + vi.FileBuildPart * numberbase + vi.FilePrivatePart; + } + private static object CreateBackupPackage(object parameter, object o) { var config = (parameter as Menu.ExecutorParameter).GetConfig< BackupPackageManagerXmlProcessor>(); var args = (parameter as Menu.ExecutorParameter).Args; diff --git a/Vrh.Log4Pro.MaintenanceConsole/Properties/AssemblyInfo.cs b/Vrh.Log4Pro.MaintenanceConsole/Properties/AssemblyInfo.cs index b8849fc..f28bcc1 100644 --- a/Vrh.Log4Pro.MaintenanceConsole/Properties/AssemblyInfo.cs +++ b/Vrh.Log4Pro.MaintenanceConsole/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.33.0.0")] -[assembly: AssemblyFileVersion("1.33.0.0")] +[assembly: AssemblyVersion("1.34.0.0")] +[assembly: AssemblyFileVersion("1.34.0.0")] -- libgit2 0.21.2