Files
2025-12-20 19:58:42 -07:00

204 lines
8.5 KiB
C#

using Mono.Options;
using Repackinator.Core.Helpers;
using XboxToolkit;
using XboxToolkit.Interface;
using Repackinator.Core.Models;
namespace Repackinator.Shell.Console
{
public static class ConsoleCompare
{
public const string Action = "Compare";
public static string First { get; set; } = string.Empty;
public static string Second { get; set; } = string.Empty;
public static bool Compare { get; set; } = false;
public static bool ShowHelp { get; set; } = false;
public static bool Wait { get; set; } = false;
public static OptionSet GetOptions()
{
return new OptionSet {
{ "f|first=", "First file to compare", f => First = f },
{ "s|second=", "Second file to compare", s => Second = s },
{ "c|compare", "Perform comparison (requires both -f and -s)", c => Compare = c != null },
{ "h|help", "show help", h => ShowHelp = h != null },
{ "w|wait", "Wait on exit", w => Wait = w != null }
};
}
public static void ShowOptionDescription()
{
System.Console.WriteLine();
System.Console.WriteLine("Compare Action...");
System.Console.WriteLine();
System.Console.WriteLine("This action is used to compare two Xbox disk images sector by sector.");
System.Console.WriteLine("You can specify both files with -f and -s, or use -c to compare files previously set.");
System.Console.WriteLine();
GetOptions().WriteOptionDescriptions(System.Console.Out);
}
public static void Process(string version, string[] args)
{
try
{
var options = GetOptions();
options.Parse(args);
if (ShowHelp)
{
ConsoleUtil.ShowHelpHeaderForAction(version, Action, options);
ConsoleUtil.ProcessWait(Wait);
return;
}
// If no parameters provided, show help
if (string.IsNullOrEmpty(First) && string.IsNullOrEmpty(Second) && !Compare)
{
throw new OptionException("No parameters specified. Use -f to set first file, -s to set second file, or -c to compare.", "compare");
}
string? firstFile = null;
string? secondFile = null;
// Load config to get/set comparison files
var config = Config.LoadConfig();
// Process first file: save to config if provided, or load from config if not provided
if (!string.IsNullOrEmpty(First))
{
if (!File.Exists(First))
{
throw new OptionException("First is not a valid file.", "first");
}
firstFile = Path.GetFullPath(First);
// Save to config for future use
if (config != null)
{
config.CompareFirst = firstFile;
Config.SaveConfig(config);
}
}
else if (config != null && !string.IsNullOrEmpty(config.CompareFirst))
{
// Load from config if not provided via command line
firstFile = config.CompareFirst;
}
// Process second file: save to config if provided, or load from config if not provided
if (!string.IsNullOrEmpty(Second))
{
if (!File.Exists(Second))
{
throw new OptionException("Second is not a valid file.", "second");
}
secondFile = Path.GetFullPath(Second);
// Save to config for future use
if (config != null)
{
config.CompareSecond = secondFile;
Config.SaveConfig(config);
}
}
else if (config != null && !string.IsNullOrEmpty(config.CompareSecond))
{
// Load from config if not provided via command line
secondFile = config.CompareSecond;
}
// If compare flag is set, ensure we have both files (from command line or config)
if (Compare)
{
if (string.IsNullOrEmpty(firstFile) || string.IsNullOrEmpty(secondFile))
{
throw new OptionException("Both first and second files must be specified (use -f to set first, or it will be loaded from config).", "compare");
}
}
if (!string.IsNullOrEmpty(firstFile) && !string.IsNullOrEmpty(secondFile))
{
if (!File.Exists(firstFile))
{
throw new OptionException("First file does not exist.", "first");
}
if (!File.Exists(secondFile))
{
throw new OptionException("Second file does not exist.", "second");
}
System.Console.WriteLine("Comparing:");
var firstSlices = ContainerUtility.GetSlicesFromFile(firstFile);
foreach (var slice in firstSlices)
{
System.Console.WriteLine(Path.GetFileName(slice));
}
System.Console.WriteLine("Against:");
var secondSlices = ContainerUtility.GetSlicesFromFile(secondFile);
foreach (var slice in secondSlices)
{
System.Console.WriteLine(Path.GetFileName(slice));
}
System.Console.WriteLine();
if (!ContainerUtility.TryAutoDetectContainerType(firstFile, out var containerReader1) || containerReader1 == null)
{
throw new Exception("Unable to detect container type for first file.");
}
if (!ContainerUtility.TryAutoDetectContainerType(secondFile, out var containerReader2) || containerReader2 == null)
{
containerReader1.Dispose();
throw new Exception("Unable to detect container type for second file.");
}
using (containerReader1)
using (containerReader2)
{
if (!containerReader1.TryMount())
{
throw new Exception("Unable to mount first container.");
}
if (!containerReader2.TryMount())
{
containerReader1.Dismount();
throw new Exception("Unable to mount second container.");
}
try
{
var previousProgress = -1.0f;
ContainerUtility.CompareContainers(containerReader1, containerReader2, s =>
{
System.Console.WriteLine(s);
}, p =>
{
var amount = (float)Math.Round(p * 100);
if (amount != previousProgress)
{
System.Console.Write($"Progress {amount}%");
System.Console.CursorLeft = 0;
previousProgress = amount;
}
});
}
finally
{
containerReader1.Dismount();
containerReader2.Dismount();
}
}
System.Console.WriteLine();
System.Console.WriteLine("Compare completed.");
}
}
catch (OptionException e)
{
ConsoleUtil.ShowOptionException(e, Action, version);
}
ConsoleUtil.ProcessWait(Wait);
}
}
}