From d622a81974420e51efa8ca8ebdc489a81cc4f404 Mon Sep 17 00:00:00 2001 From: Benjamin Auquite Date: Sun, 21 May 2023 21:05:59 -0500 Subject: [PATCH] ditto --- KOTORModSync.Core/Utility/Serializer.cs | 42 +++++++++------ KOTORModSync.Core/installer.cs | 71 ++++++++++++++++--------- KOTORModSync.GUI/MainWindow.axaml.cs | 2 +- 3 files changed, 75 insertions(+), 40 deletions(-) diff --git a/KOTORModSync.Core/Utility/Serializer.cs b/KOTORModSync.Core/Utility/Serializer.cs index b50095e..e63f660 100644 --- a/KOTORModSync.Core/Utility/Serializer.cs +++ b/KOTORModSync.Core/Utility/Serializer.cs @@ -373,28 +373,37 @@ public static async Task> EnumerateFilesWithWildcards(string direct { var matchingFiles = new List(); - string regexPattern = "^" + Regex.Escape(pattern) - .Replace("\\*", ".*") - .Replace("\\?", ".") - + "$"; + string directoryPath = Path.GetDirectoryName(directory); + string directoryNamePattern = Path.GetFileName(directory); - IEnumerable files = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories); - foreach (string file in files) + IEnumerable matchingDirectories = Directory.GetDirectories(directoryPath, directoryNamePattern, SearchOption.TopDirectoryOnly); + + foreach (string matchingDirectory in matchingDirectories) { - if (Regex.IsMatch(Path.GetFileName(file), regexPattern)) + string filePattern = Path.GetFileName(pattern); + string regexPattern = "^" + Regex.Escape(filePattern) + .Replace("\\*", ".*") + .Replace("\\?", ".") + + "$"; + + IEnumerable files = Directory.EnumerateFiles(matchingDirectory, "*", SearchOption.AllDirectories); + foreach (string file in files) { - matchingFiles.Add(file); + if (Regex.IsMatch(Path.GetFileName(file), regexPattern)) + { + matchingFiles.Add(file); + } } - } - if (!excludeDirectories) - { - IEnumerable directories = Directory.EnumerateDirectories(directory, "*", SearchOption.AllDirectories); - foreach (string subdirectory in directories) + if (!excludeDirectories) { - if (Regex.IsMatch(Path.GetFileName(subdirectory), regexPattern)) + IEnumerable directories = Directory.EnumerateDirectories(matchingDirectory, "*", SearchOption.AllDirectories); + foreach (string subdirectory in directories) { - matchingFiles.Add(subdirectory); + if (Regex.IsMatch(Path.GetFileName(subdirectory), regexPattern)) + { + matchingFiles.Add(subdirectory); + } } } } @@ -404,6 +413,9 @@ public static async Task> EnumerateFilesWithWildcards(string direct + + + public static List ReadComponentsFromFile(string filePath) { try diff --git a/KOTORModSync.Core/installer.cs b/KOTORModSync.Core/installer.cs index 731b30f..357c9f1 100644 --- a/KOTORModSync.Core/installer.cs +++ b/KOTORModSync.Core/installer.cs @@ -99,21 +99,23 @@ public async Task ExtractFileAsync() try { (List sourcePaths, DirectoryInfo _) = await ParsePathsAsync(); + List extractionTasks = new List(); + + // Use SemaphoreSlim to limit concurrent extractions + SemaphoreSlim semaphore = new SemaphoreSlim(5); // Limiting to 5 concurrent extractions + foreach (string sourcePath in sourcePaths) { - var thisFile = new FileInfo(sourcePath); - Logger.Log($"File path: {thisFile.FullName}"); + await semaphore.WaitAsync(); // Acquire a semaphore slot - if (ArchiveHelper.IsArchive(thisFile.Extension)) + extractionTasks.Add(Task.Run(async () => { - List archiveEntries = ArchiveHelper.TraverseArchiveEntries(thisFile.FullName); - - foreach (ArchiveEntry entry in archiveEntries) + try { - string destinationFolder = Path.GetFileNameWithoutExtension(thisFile.Name); - string destinationPath = Path.Combine(thisFile.Directory.FullName, destinationFolder, entry.Path); - Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); - using (Stream outputStream = File.Create(destinationPath)) + var thisFile = new FileInfo(sourcePath); + Logger.Log($"File path: {thisFile.FullName}"); + + if (ArchiveHelper.IsArchive(thisFile.Extension)) { using (FileStream stream = File.OpenRead(thisFile.FullName)) { @@ -131,31 +133,50 @@ public async Task ExtractFileAsync() { archive = SevenZipArchive.Open(stream); } - Logger.Log($"Attempting to extract {thisFile.Name}"); + if (archive != null) { - IArchiveEntry archiveEntry = archive.Entries.FirstOrDefault(e => e.Key == entry.Path); - if (archiveEntry != null && !archiveEntry.IsDirectory) + List archiveEntries = ArchiveHelper.TraverseArchiveEntries(thisFile.FullName); + + // Extract entries in parallel + await Task.WhenAll(archiveEntries.Select(async entry => { - Logger.Log($"Extracting {archiveEntry.Key}"); - using (Stream entryStream = archiveEntry.OpenEntryStream()) + string destinationFolder = Path.GetFileNameWithoutExtension(thisFile.Name); + string destinationPath = Path.Combine(thisFile.Directory.FullName, destinationFolder, entry.Path); + Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); + + using (Stream outputStream = File.Create(destinationPath)) { - entryStream.CopyTo(outputStream); + IArchiveEntry archiveEntry = archive.Entries.FirstOrDefault(e => e.Key == entry.Path); + if (archiveEntry != null && !archiveEntry.IsDirectory) + { + Logger.Log($"Extracting {archiveEntry.Key}"); + using (Stream entryStream = archiveEntry.OpenEntryStream()) + { + await entryStream.CopyToAsync(outputStream); + } + } } - } + })); } } } + else + { + var ex = new ArgumentNullException($"{this.ParentComponent.Name} failed to extract file {thisFile}"); + Logger.LogException(ex); + throw ex; + } } - } - else - { - var ex = new ArgumentNullException($"{this.ParentComponent.Name} failed to extract file {thisFile}"); - Logger.LogException(ex); - throw ex; - } + finally + { + semaphore.Release(); // Release the semaphore slot + } + })); } + await Task.WhenAll(extractionTasks); // Wait for all extraction tasks to complete + return true; // Extraction succeeded } catch (Exception ex) @@ -166,6 +187,8 @@ public async Task ExtractFileAsync() } } + + public async Task DeleteFileAsync() { try diff --git a/KOTORModSync.GUI/MainWindow.axaml.cs b/KOTORModSync.GUI/MainWindow.axaml.cs index bd8178f..473df68 100644 --- a/KOTORModSync.GUI/MainWindow.axaml.cs +++ b/KOTORModSync.GUI/MainWindow.axaml.cs @@ -417,7 +417,7 @@ private bool CheckForChanges() private async void SaveButton_Click(object sender, RoutedEventArgs e) { if (currentComponent is null) - currentComponent = leftTreeView.SelectedItem as Core.Component; + currentComponent = leftTreeView.SelectedItem as Component; if (currentComponent is null) { var informationDialog = new InformationDialog();