From 0bb5fbdf87b3f4b0a4a783a1431115a08183e6a6 Mon Sep 17 00:00:00 2001 From: nihil Date: Sat, 10 May 2025 21:13:09 +0200 Subject: [PATCH] implemented analyze command --- RedundancyFinder/RedundancyFinder.csproj | 1 + RedundancyFinderCLI/AnalyzeCommand.cs | 108 ++++++++++++++++++ RedundancyFinderCLI/FinderCommand.cs | 9 ++ RedundancyFinderCLI/Program.cs | 2 + .../Properties/launchSettings.json | 4 + .../RedundancyFinderCLI.csproj | 1 + RedundancyFixer.sln | 6 +- 7 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 RedundancyFinderCLI/AnalyzeCommand.cs diff --git a/RedundancyFinder/RedundancyFinder.csproj b/RedundancyFinder/RedundancyFinder.csproj index bb23fb7..92ae209 100644 --- a/RedundancyFinder/RedundancyFinder.csproj +++ b/RedundancyFinder/RedundancyFinder.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + Debug;Release;Analyze diff --git a/RedundancyFinderCLI/AnalyzeCommand.cs b/RedundancyFinderCLI/AnalyzeCommand.cs new file mode 100644 index 0000000..121d09c --- /dev/null +++ b/RedundancyFinderCLI/AnalyzeCommand.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using Newtonsoft.Json; +using RedundancyFinder; +using Spectre.Console; +using Spectre.Console.Cli; +namespace RedundancyFinderCLI +{ + internal sealed class AnalyzeCommand : Command + { + public sealed class Settings : CommandSettings + { + [Description("Path to analyze.")] + [DefaultValue("redundancies.json")] + [CommandArgument(0, "[path]")] + public string? Path { get; init; } + + [Description("File extensions to search for. Comma separated.")] + [CommandOption("-e|--extensions")] + [DefaultValue(".jpg,.webp,.raw,.pdf,.xsl,.xslx,.doc,.docx,.txt,.jpeg,.mov,.mp4,.mp3,.wav,.bmp,.gif,.png,.cu,.mid,.msb ,.mov,.avi,.wmv,.flv,.m4v,.bak ,.cpr ,.xml,.psd")] + public string? Extensions { get; init; } + + [Description("Show all information.")] + [CommandOption("-v|--verbose")] + [DefaultValue(false)] + public bool Verbose { get; init; } + + } + public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) + { + WriteLine($"[yellow]Analyzing {settings.Path}[/]"); + + var redundancies = JsonConvert.DeserializeObject>(File.ReadAllText(settings.Path)); + + + var groups = redundancies + .GroupBy(x => Path.GetExtension(x.Value.Paths[0]), x => x.Value) + .ToDictionary(x => x.Key, x => new + { + FileSize = x.Sum(y => y.FileSize), + RedundancySize = x.Sum(y => y.FileSize) * (x.Sum(y => y.Paths.Count) - 1), + RedundancyCount = x.Sum(y => y.Paths.Count)-1, + }); + // x => new { FileSize = x, RedundancySize = x.Sum()*(x.Count()-1)} + var extensions = settings.Extensions.Split(",", StringSplitOptions.RemoveEmptyEntries); + var table = new Table(); + + table.AddColumn("Type"); + table.AddColumn(new TableColumn("Size").RightAligned()); + table.AddColumn(new TableColumn("Redundancy size").RightAligned()); + table.AddColumn(new TableColumn("Redundancy count").RightAligned()); + foreach (var extension in extensions) + { + if (groups.ContainsKey(extension)) + { + + var size = groups[extension].FileSize; + var sizeFormat = GetSizeFormat((ulong)size); + + var redundancySize = groups[extension].RedundancySize; + var redundancySizeFormat = GetSizeFormat((ulong)redundancySize); + table.AddRow( + new Text(extension), + new Markup($"[green]{sizeFormat}[/]"), + new Markup($"[yellow]{redundancySizeFormat}[/]"), + new Markup($"{groups[extension].RedundancyCount}")); + } + } + AnsiConsole.Write(table); + return 0; + } + + + private void WriteLine(string v) + { + string now = Markup.Escape($"[{DateTime.Now.ToString("HH:mm:ss")}]"); + AnsiConsole.MarkupLine($"[gray]{now}[/] {v}"); + } + + private static string GetSizeFormat(ulong totalSize) + { + string sizeUnit = "B"; + double size = totalSize; + while (size > 1024) + { + size /= 1024d; + sizeUnit = sizeUnit switch + { + "B" => "KB", + "KB" => "MB", + "MB" => "GB", + "GB" => "TB", + _ => sizeUnit + }; + + } + string sizeFormat = $"{size:.00} {sizeUnit}"; + return sizeFormat; + } + } +} diff --git a/RedundancyFinderCLI/FinderCommand.cs b/RedundancyFinderCLI/FinderCommand.cs index 64a7bbb..3d02653 100644 --- a/RedundancyFinderCLI/FinderCommand.cs +++ b/RedundancyFinderCLI/FinderCommand.cs @@ -50,6 +50,15 @@ namespace RedundancyFinderCLI SaveRedundancies(finder, settings.OutputPath); }; + // Register the CancelKeyPress event to handle Ctrl+C + Console.CancelKeyPress += (sender, e) => + { + e.Cancel = true; // Prevent the process from terminating immediately + WriteLine("[yellow]Ctrl+C detected. Saving redundancies before exiting...[/]"); + SaveRedundancies(finder, settings.OutputPath ?? "redundancies.json"); + Environment.Exit(0); // Exit the application gracefully + }; + // Load existing redundancies if the output file exists if (File.Exists(settings.OutputPath)) { diff --git a/RedundancyFinderCLI/Program.cs b/RedundancyFinderCLI/Program.cs index 7caf140..d2d9c0a 100644 --- a/RedundancyFinderCLI/Program.cs +++ b/RedundancyFinderCLI/Program.cs @@ -12,7 +12,9 @@ internal class Program var app = new CommandApp(); app.Configure(config => { + config.AddCommand("analyze"); #if DEBUG + config.PropagateExceptions(); config.ValidateExamples(); #endif diff --git a/RedundancyFinderCLI/Properties/launchSettings.json b/RedundancyFinderCLI/Properties/launchSettings.json index e82bfb2..cc974c5 100644 --- a/RedundancyFinderCLI/Properties/launchSettings.json +++ b/RedundancyFinderCLI/Properties/launchSettings.json @@ -3,6 +3,10 @@ "RedundancyFinderCLI": { "commandName": "Project", "commandLineArgs": "C:\\Users\\daskn\\Pictures\\ -v" + }, + "Analyze": { + "commandName": "Project", + "commandLineArgs": "analyze" } } } \ No newline at end of file diff --git a/RedundancyFinderCLI/RedundancyFinderCLI.csproj b/RedundancyFinderCLI/RedundancyFinderCLI.csproj index 01dc379..9b8afba 100644 --- a/RedundancyFinderCLI/RedundancyFinderCLI.csproj +++ b/RedundancyFinderCLI/RedundancyFinderCLI.csproj @@ -5,6 +5,7 @@ net8.0 enable enable + Debug;Release;Analyze diff --git a/RedundancyFixer.sln b/RedundancyFixer.sln index 7209dda..e9034e6 100644 --- a/RedundancyFixer.sln +++ b/RedundancyFixer.sln @@ -1,11 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.13.35818.85 d17.13 +VisualStudioVersion = 17.13.35818.85 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedundancyFinder", "RedundancyFinder\RedundancyFinder.csproj", "{925C533F-2205-4848-B742-CB013F81DF91}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RedundancyFinder", "RedundancyFinder\RedundancyFinder.csproj", "{925C533F-2205-4848-B742-CB013F81DF91}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedundancyFinderCLI", "RedundancyFinderCLI\RedundancyFinderCLI.csproj", "{7187EE24-4F0D-48F3-B76C-DAECD4A96F76}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RedundancyFinderCLI", "RedundancyFinderCLI\RedundancyFinderCLI.csproj", "{7187EE24-4F0D-48F3-B76C-DAECD4A96F76}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution