diff --git a/src/ModVerify.CliApp/ModFinderService.cs b/src/ModVerify.CliApp/ModFinderService.cs index ab61067..71c96f6 100644 --- a/src/ModVerify.CliApp/ModFinderService.cs +++ b/src/ModVerify.CliApp/ModFinderService.cs @@ -29,9 +29,9 @@ public ModFinderService(IServiceProvider serviceProvider) _logger = _serviceProvider.GetService()?.CreateLogger(GetType()); } - public GameFinderResult FindAndAddModInCurrentDirectory() + public GameFinderResult FindAndAddModInDirectory(string path) { - var currentDirectory = _fileSystem.DirectoryInfo.New(Environment.CurrentDirectory); + var currentDirectory = _fileSystem.DirectoryInfo.New(path); // Assuming the currentDir is inside a Mod's directory, we need to go up two level (Game/Mods/ModDir) var potentialGameDirectory = currentDirectory.Parent?.Parent; @@ -90,4 +90,9 @@ public GameFinderResult FindAndAddModInCurrentDirectory() return new GameFinderResult(foc, eaw); } + + public GameFinderResult FindAndAddModInCurrentDirectory() + { + return FindAndAddModInDirectory(Environment.CurrentDirectory); + } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModVerify.CliApp.csproj b/src/ModVerify.CliApp/ModVerify.CliApp.csproj index 46edaae..a76e648 100644 --- a/src/ModVerify.CliApp/ModVerify.CliApp.csproj +++ b/src/ModVerify.CliApp/ModVerify.CliApp.csproj @@ -19,6 +19,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/ModVerify.CliApp/Program.cs b/src/ModVerify.CliApp/Program.cs index 7800a90..95f4228 100644 --- a/src/ModVerify.CliApp/Program.cs +++ b/src/ModVerify.CliApp/Program.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.IO.Abstractions; using System.Linq; using System.Runtime.CompilerServices; @@ -10,6 +11,7 @@ using AnakinRaW.CommonUtilities.Hashing; using AnakinRaW.CommonUtilities.Registry; using AnakinRaW.CommonUtilities.Registry.Windows; +using CommandLine; using EawModinfo.Spec; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -30,45 +32,62 @@ namespace ModVerify.CliApp; internal class Program { private static IServiceProvider _services = null!; + private static CliOptions _options; - static async Task Main(string[] args) + private static async Task Main(string[] args) { + _options = Parser.Default.ParseArguments(args).WithParsed(o => { }).Value; _services = CreateAppServices(); - var gameFinderResult = new ModFinderService(_services).FindAndAddModInCurrentDirectory(); - - var game = gameFinderResult.Game; - Console.WriteLine($"0: {game.Name}"); - - var list = new List { game }; + GameFinderResult gameFinderResult; + IPlayableObject? selectedObject = null; - var counter = 1; - foreach (var mod in game.Mods) + if (!string.IsNullOrEmpty(_options.Path)) { - var isSteam = mod.Type == ModType.Workshops; - var line = $"{counter++}: {mod.Name}"; - if (isSteam) - line += "*"; - Console.WriteLine(line); - list.Add(mod); + var fs = _services.GetService(); + if (!fs!.Directory.Exists(_options.Path)) + throw new DirectoryNotFoundException($"No directory found at {_options.Path}"); + + gameFinderResult = new ModFinderService(_services).FindAndAddModInDirectory(_options.Path); + var selectedPath = fs.Path.GetFullPath(_options.Path).ToUpper(); + selectedObject = + (from mod1 in gameFinderResult.Game.Mods.OfType() + let modPath = fs.Path.GetFullPath(mod1.Directory.FullName) + where selectedPath.Equals(modPath) + select mod1).FirstOrDefault(); + if (selectedObject == null) throw new Exception($"The selected directory {_options.Path} is not a mod."); } + else + { + gameFinderResult = new ModFinderService(_services).FindAndAddModInCurrentDirectory(); + var game = gameFinderResult.Game; + Console.WriteLine($"0: {game.Name}"); - IPlayableObject? selectedObject = null; + var list = new List { game }; - do - { - Console.Write("Select a game or mod to verify: "); - var numberString = Console.ReadLine(); + var counter = 1; + foreach (var mod in game.Mods) + { + var isSteam = mod.Type == ModType.Workshops; + var line = $"{counter++}: {mod.Name}"; + if (isSteam) + line += "*"; + Console.WriteLine(line); + list.Add(mod); + } - if (int.TryParse(numberString, out var number)) + do { + Console.Write("Select a game or mod to verify: "); + var numberString = Console.ReadLine(); + + if (!int.TryParse(numberString, out var number)) continue; if (number < list.Count) selectedObject = list[number]; - } - } while (selectedObject is null); + } while (selectedObject is null); + } Console.WriteLine($"Verifying {selectedObject.Name}..."); - var verifyPipeline = BuildPipeline(selectedObject, gameFinderResult.FallbackGame); try @@ -121,7 +140,7 @@ private static IServiceProvider CreateAppServices() RuntimeHelpers.RunClassConstructor(typeof(IMegArchive).TypeHandle); AloServiceContribution.ContributeServices(serviceCollection); serviceCollection.CollectPgServiceContributions(); - + PetroglyphEngineServiceContribution.ContributeServices(serviceCollection); ModVerifyServiceContribution.ContributeServices(serviceCollection); @@ -137,8 +156,25 @@ private static void ConfigureLogging(ILoggingBuilder loggingBuilder) #if DEBUG logLevel = LogLevel.Debug; loggingBuilder.AddDebug(); +#else + if (_options.Verbose) + { + logLevel = LogLevel.Debug; + loggingBuilder.AddDebug(); + } #endif loggingBuilder.AddConsole(); + loggingBuilder.SetMinimumLevel(logLevel); + } + + + internal class CliOptions + { + [Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")] + public bool Verbose { get; set; } + + [Option('p', "path", Required = false, HelpText = "The path to a mod directory to verify.")] + public string Path { get; set; } } } diff --git a/src/ModVerify/Steps/DuplicateFinderStep.cs b/src/ModVerify/Steps/DuplicateFinderStep.cs index f74721e..47251c8 100644 --- a/src/ModVerify/Steps/DuplicateFinderStep.cs +++ b/src/ModVerify/Steps/DuplicateFinderStep.cs @@ -42,7 +42,7 @@ private string CreateDuplicateErrorMessage(string context, ReadOnlyFrugalList var message = $"{context} '{firstEntry.Name}' ({firstEntry.Crc32}) has duplicate definitions: "; foreach (var entry in entries) - message += $"['{entry.Name}' in {entry.Location.XmlFile}] "; + message += $"['{entry.Name}' in {entry.Location.XmlFile}:{entry.Location.Line}] "; return message.TrimEnd(); }