From dac8dcca6226b47b05a17c14c399a3a1afd1a0b8 Mon Sep 17 00:00:00 2001 From: Matt Pannella Date: Sat, 9 Mar 2024 09:49:05 -0500 Subject: [PATCH] Zip progress bar (#274) * new zip helper with progress * missed one * version bump * hm, this isnt working right * moved progress bar to new helper fixed recursive logic for file copy --- pupdate.csproj | 2 +- src/helpers/ConsoleHelper.cs | 46 ++++++++++++ src/helpers/HttpHelper.cs | 14 +--- src/helpers/Util.cs | 15 +++- src/helpers/ZipHelper.cs | 78 +++++++++++++++++++++ src/partials/Program.GameAndWatch.cs | 2 +- src/partials/Program.PocketLibraryImages.cs | 2 +- src/partials/Program.UpdateSelfAndRun.cs | 4 +- src/services/CoresService.Extras.cs | 4 +- src/services/CoresService.Helpers.cs | 2 +- src/services/CoresService.Jotego.cs | 2 +- src/services/PlatformImagePacksService.cs | 7 +- 12 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 src/helpers/ConsoleHelper.cs create mode 100644 src/helpers/ZipHelper.cs diff --git a/pupdate.csproj b/pupdate.csproj index 8d1f8146..67756852 100644 --- a/pupdate.csproj +++ b/pupdate.csproj @@ -6,7 +6,7 @@ net7.0 enable disable - 3.8.1 + 3.9.0 Keep your Analogue Pocket up to date 2024 Matt Pannella Matt Pannella diff --git a/src/helpers/ConsoleHelper.cs b/src/helpers/ConsoleHelper.cs new file mode 100644 index 00000000..e46af4fe --- /dev/null +++ b/src/helpers/ConsoleHelper.cs @@ -0,0 +1,46 @@ +using System.IO.Compression; + +namespace Pannella.Helpers; + +public class ConsoleHelper +{ + public static void ShowProgressBar(int current, int total) + { + var progress = (double)current / (double)total; + + var progressWidth = Console.WindowWidth - 14; + var progressBarWidth = (int)(progress * progressWidth); + var progressBar = new string('=', progressBarWidth); + var emptyProgressBar = new string(' ', progressWidth - progressBarWidth); + + Console.Write($"\r{progressBar}{emptyProgressBar}] {(progress * 100):0.00}%"); + + if (current == total) + { + Console.CursorLeft = 0; + Console.Write(new string(' ', Console.WindowWidth)); + Console.CursorLeft = 0; + Console.Write("\r"); + } + } + + public static void ShowProgressBar(long current, long total) + { + var progress = (double)current / total; + + var progressWidth = Console.WindowWidth - 14; + var progressBarWidth = (int)(progress * progressWidth); + var progressBar = new string('=', progressBarWidth); + var emptyProgressBar = new string(' ', progressWidth - progressBarWidth); + + Console.Write($"\r{progressBar}{emptyProgressBar}] {(progress * 100):0.00}%"); + + if (current == total) + { + Console.CursorLeft = 0; + Console.Write(new string(' ', Console.WindowWidth)); + Console.CursorLeft = 0; + Console.Write("\r"); + } + } +} \ No newline at end of file diff --git a/src/helpers/HttpHelper.cs b/src/helpers/HttpHelper.cs index a21e87eb..50a07891 100644 --- a/src/helpers/HttpHelper.cs +++ b/src/helpers/HttpHelper.cs @@ -86,19 +86,7 @@ public void DownloadFile(string uri, string outputPath, int timeout = 100) if (console) { - var progressWidth = Console.WindowWidth - 14; - var progressBarWidth = (int)(progress * progressWidth); - var progressBar = new string('=', progressBarWidth); - var emptyProgressBar = new string(' ', progressWidth - progressBarWidth); - - Console.Write($"\r{progressBar}{emptyProgressBar}] {(progress * 100):0.00}%"); - - if (readSoFar == totalSize) - { - Console.CursorLeft = 0; - Console.Write(new string(' ', Console.WindowWidth)); - Console.CursorLeft = 0; - } + ConsoleHelper.ShowProgressBar(readSoFar, totalSize); } DownloadProgressEventArgs args = new() diff --git a/src/helpers/Util.cs b/src/helpers/Util.cs index 31928999..1c864e3d 100644 --- a/src/helpers/Util.cs +++ b/src/helpers/Util.cs @@ -17,6 +17,10 @@ public enum HashTypes } public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite) + { + _copyDirectory(sourceDir, destinationDir, recursive, overwrite); + } + private static int _copyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite, int currentFileCount = 0, int? totalFiles = null) { // Get information about the source directory var dir = new DirectoryInfo(sourceDir); @@ -33,12 +37,19 @@ public static void CopyDirectory(string sourceDir, string destinationDir, bool r // Create the destination directory Directory.CreateDirectory(destinationDir); + List allfiles = Directory.GetFiles(sourceDir, "*",SearchOption.AllDirectories).ToList(); + + int total = (totalFiles == null) ? allfiles.Count() : (int)totalFiles; + int count = currentFileCount; // Get the files in the source directory and copy to the destination directory foreach (FileInfo file in dir.GetFiles()) { string targetFilePath = Path.Combine(destinationDir, file.Name); file.CopyTo(targetFilePath, overwrite); + + count++; + ConsoleHelper.ShowProgressBar(count, total); } // If recursive and copying subdirectories, recursively call this method @@ -48,9 +59,11 @@ public static void CopyDirectory(string sourceDir, string destinationDir, bool r { string newDestinationDir = Path.Combine(destinationDir, subDir.Name); - CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite); + count = _copyDirectory(subDir.FullName, newDestinationDir, true, overwrite, count, total); } } + + return count; } public static void CleanDir(string source, string path = "", bool preservePlatformsFolder = false, string platform = "") diff --git a/src/helpers/ZipHelper.cs b/src/helpers/ZipHelper.cs new file mode 100644 index 00000000..b7f50b6f --- /dev/null +++ b/src/helpers/ZipHelper.cs @@ -0,0 +1,78 @@ +using System.IO.Compression; + +namespace Pannella.Helpers; + +public class ZipHelper +{ + private static void UpdateProgress(object sender, ZipProgress zipProgress) + { + ConsoleHelper.ShowProgressBar(zipProgress.Processed, zipProgress.Total); + } + + public static void ExtractToDirectory(string zipFile, string destination, bool overwrite = false) + { + Progress _progress = new Progress(); + _progress.ProgressChanged += UpdateProgress; + var stream = new FileStream(zipFile, FileMode.Open); + var zip = new ZipArchive(stream); + zip.ExtractToDirectory(destination, _progress, overwrite); + stream.Close(); + } +} + +public class ZipProgress +{ + public ZipProgress(int total, int processed, string currentItem) + { + Total = total; + Processed = processed; + CurrentItem = currentItem; + } + public int Total { get; } + public int Processed { get; } + public string CurrentItem { get; } +} + +public static class ZipExtension +{ + public static void ExtractToDirectory(this ZipArchive zipFile, string target, IProgress progress) + { + ExtractToDirectory(zipFile, target, progress, overwrite: false); + } + + public static void ExtractToDirectory(this ZipArchive zipFile, string target, IProgress progress, bool overwrite) + { + DirectoryInfo info = Directory.CreateDirectory(target); + string targetPath = info.FullName; + + int count = 0; + foreach (ZipArchiveEntry entry in zipFile.Entries) + { + count++; + string fileDestinationPath = Path.GetFullPath(Path.Combine(targetPath, entry.FullName)); + + if (!fileDestinationPath.StartsWith(targetPath, StringComparison.OrdinalIgnoreCase)) + { + throw new IOException("File is extracting to outside of the folder specified."); + } + + var zipProgress = new ZipProgress(zipFile.Entries.Count, count, entry.FullName); + progress.Report(zipProgress); + + if (Path.GetFileName(fileDestinationPath).Length == 0) + { + if (entry.Length != 0) + { + throw new IOException("Directory entry with data."); + } + + Directory.CreateDirectory(fileDestinationPath); + } + else + { + Directory.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)); + entry.ExtractToFile(fileDestinationPath, overwrite: overwrite); + } + } + } +} \ No newline at end of file diff --git a/src/partials/Program.GameAndWatch.cs b/src/partials/Program.GameAndWatch.cs index be2aa41b..f94a6abd 100644 --- a/src/partials/Program.GameAndWatch.cs +++ b/src/partials/Program.GameAndWatch.cs @@ -26,7 +26,7 @@ private static void BuildGameAndWatchRoms() { Directory.CreateDirectory(downloadPath); HttpHelper.Instance.DownloadFile(asset.browser_download_url, filename); - ZipFile.ExtractToDirectory(filename, downloadPath, true); + ZipHelper.ExtractToDirectory(filename, downloadPath, true); } break; diff --git a/src/partials/Program.PocketLibraryImages.cs b/src/partials/Program.PocketLibraryImages.cs index 7e384228..0a6efef1 100644 --- a/src/partials/Program.PocketLibraryImages.cs +++ b/src/partials/Program.PocketLibraryImages.cs @@ -26,7 +26,7 @@ private static void DownloadPockLibraryImages() if (Directory.Exists(extractPath)) Directory.Delete(extractPath, true); - ZipFile.ExtractToDirectory(localFile, extractPath); + ZipHelper.ExtractToDirectory(localFile, extractPath); File.Delete(localFile); Util.CopyDirectory(extractPath, ServiceHelper.UpdateDirectory, true, true); diff --git a/src/partials/Program.UpdateSelfAndRun.cs b/src/partials/Program.UpdateSelfAndRun.cs index fb43f078..842f3360 100644 --- a/src/partials/Program.UpdateSelfAndRun.cs +++ b/src/partials/Program.UpdateSelfAndRun.cs @@ -1,7 +1,7 @@ using System.Diagnostics; -using System.IO.Compression; using System.Reflection; using System.Text; +using Pannella.Helpers; namespace Pannella; @@ -40,7 +40,7 @@ private static int UpdateSelfAndRun(string directory, string[] updaterArgs) // Extract update Console.WriteLine($"Extracting {updateLocation} to {directory}"); - ZipFile.ExtractToDirectory(updateLocation, directory, true); + ZipHelper.ExtractToDirectory(updateLocation, directory, true); // Execute Console.WriteLine($"Executing {execLocation}"); diff --git a/src/services/CoresService.Extras.cs b/src/services/CoresService.Extras.cs index 17ca0c90..ea3b8278 100644 --- a/src/services/CoresService.Extras.cs +++ b/src/services/CoresService.Extras.cs @@ -88,7 +88,7 @@ private void DownloadPocketExtrasPlatform(PocketExtra pocketExtra, string path, if (Directory.Exists(extractPath)) Directory.Delete(extractPath, true); - ZipFile.ExtractToDirectory(localFile, extractPath); + ZipHelper.ExtractToDirectory(localFile, extractPath); File.Delete(localFile); if (pocketExtra.has_placeholders) @@ -247,7 +247,7 @@ private void DownloadPocketExtras(PocketExtra pocketExtra, string path, bool dow if (Directory.Exists(extractPath)) Directory.Delete(extractPath, true); - ZipFile.ExtractToDirectory(localFile, extractPath); + ZipHelper.ExtractToDirectory(localFile, extractPath); File.Delete(localFile); Util.CopyDirectory(sourceAssetsCore, destinationAssetsCore, true, true); diff --git a/src/services/CoresService.Helpers.cs b/src/services/CoresService.Helpers.cs index 6868aefe..07147e76 100644 --- a/src/services/CoresService.Helpers.cs +++ b/src/services/CoresService.Helpers.cs @@ -61,7 +61,7 @@ private bool InstallGithubAsset(string identifier, string platformId, string dow string tempDir = Path.Combine(this.installPath, "temp", identifier); - ZipFile.ExtractToDirectory(zipPath, tempDir, true); + ZipHelper.ExtractToDirectory(zipPath, tempDir, true); // Clean problematic directories and files. Util.CleanDir(tempDir, this.installPath, this.settingsService.GetConfig().preserve_platforms_folder, platformId); diff --git a/src/services/CoresService.Jotego.cs b/src/services/CoresService.Jotego.cs index 42c1df0a..4a1c23f8 100644 --- a/src/services/CoresService.Jotego.cs +++ b/src/services/CoresService.Jotego.cs @@ -95,7 +95,7 @@ public bool ExtractBetaKey() if (File.Exists(zipFile)) { WriteMessage("JT beta key detected. Extracting..."); - ZipFile.ExtractToDirectory(zipFile, keyPath, true); + ZipHelper.ExtractToDirectory(zipFile, keyPath, true); return true; } diff --git a/src/services/PlatformImagePacksService.cs b/src/services/PlatformImagePacksService.cs index 335378d2..e4a8a6c6 100644 --- a/src/services/PlatformImagePacksService.cs +++ b/src/services/PlatformImagePacksService.cs @@ -70,8 +70,7 @@ public void Install(string owner, string repository, string variant) WriteMessage("Installing..."); string extractPath = Path.Combine(this.installPath, "temp"); - - ZipFile.ExtractToDirectory(localFile, extractPath, true); + ZipHelper.ExtractToDirectory(localFile, extractPath, true); string imagePack = FindPlatformImagePack(extractPath); string target = Path.Combine(this.installPath, "Platforms", "_images"); @@ -80,7 +79,7 @@ public void Install(string owner, string repository, string variant) Directory.Delete(extractPath, true); File.Delete(localFile); - WriteMessage("All Done"); + WriteMessage("Installation complete."); } private static string FindPlatformImagePack(string temp) @@ -104,4 +103,4 @@ private static string FindPlatformImagePack(string temp) throw new Exception("Can't find image pack"); } -} +} \ No newline at end of file