diff --git a/Wabbajack.CLI/CLIUtils.cs b/Wabbajack.CLI/CLIUtils.cs index 7fe21152..708b268c 100644 --- a/Wabbajack.CLI/CLIUtils.cs +++ b/Wabbajack.CLI/CLIUtils.cs @@ -8,19 +8,52 @@ using Wabbajack.Common; namespace Wabbajack.CLI { + /// + /// Abstract class to mark attributes which need validating + /// [AttributeUsage(AttributeTargets.Property)] - internal class IsFileAttribute : Attribute { } + internal abstract class AValidateAttribute : Attribute + { + /// + /// Exit the application if validation failed. Will just log if set to false + /// + public bool Exit { get; set; } - [AttributeUsage(AttributeTargets.Property)] - internal class IsDirectoryAttribute : Attribute { } + /// + /// Custom message if validation failed. Use placeholder %1 to insert the value + /// + public string? CustomMessage { get; set; } + } + + /// + /// Validating if the file exists + /// + internal class IsFileAttribute : AValidateAttribute { } + + /// + /// Validating if the directory exists + /// + internal class IsDirectoryAttribute : AValidateAttribute + { + /// + /// Create the directory if it does not exists + /// + public bool Create { get; set; } + } internal static class CLIUtils { + /// + /// Validates all Attributes of type + /// + /// The verb to validate + /// internal static bool HasValidArguments(AVerb verb) { var props = verb.GetType().GetProperties().Where(p => { - var hasAttr = p.HasAttribute(typeof(OptionAttribute)); + var hasAttr = p.HasAttribute(typeof(OptionAttribute)) + && p.HasAttribute(typeof(AValidateAttribute)); if (!hasAttr) return false; @@ -32,7 +65,7 @@ namespace Wabbajack.CLI return false; var stringValue = (string)value; - return string.IsNullOrWhiteSpace(stringValue); + return !string.IsNullOrWhiteSpace(stringValue); }); var valid = true; @@ -49,21 +82,68 @@ namespace Wabbajack.CLI return; var value = (string)valueObject; + var attribute = (AValidateAttribute)p.GetAttribute(typeof(AValidateAttribute)); + var isFile = false; if (p.HasAttribute(typeof(IsFileAttribute))) { + isFile = true; valid = File.Exists(value); } if (p.HasAttribute(typeof(IsDirectoryAttribute))) { - valid = Directory.Exists(value); + var dirAttribute = (IsDirectoryAttribute)attribute; + var exists = Directory.Exists(value); + + if (!exists) + { + if (dirAttribute.Create) + { + Log($"Directory {value} does not exist and will be created"); + Directory.CreateDirectory(value); + } + else + valid = false; + } } + + if (valid) + return; + + var message = string.IsNullOrWhiteSpace(attribute.CustomMessage) + ? isFile + ? $"The file {value} does not exist!" + : $"The folder {value} does not exist!" + : attribute.CustomMessage.Replace("%1", value); + + if (attribute.Exit) + Exit(message, -1); + else + Log(message); }); return valid; } + /// + /// Gets an attribute of a specific type + /// + /// + /// + /// + internal static Attribute GetAttribute(this MemberInfo member, Type attribute) + { + var attributes = member.GetCustomAttributes(attribute); + return attributes.ElementAt(0); + } + + /// + /// Checks if a has a custom attribute + /// + /// + /// + /// internal static bool HasAttribute(this MemberInfo member, Type attribute) { var attributes = member.GetCustomAttributes(attribute); diff --git a/Wabbajack.CLI/Properties/launchSettings.json b/Wabbajack.CLI/Properties/launchSettings.json new file mode 100644 index 00000000..ad46cac6 --- /dev/null +++ b/Wabbajack.CLI/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Wabbajack.CLI": { + "commandName": "Project", + "commandLineArgs": "change-download --input=\"S:\\Modding FAST\\Wabbajack\\downloads\" --output=\"S:\\Modding FAST\\test\" --modlist=\"S:\\Modding FAST\\Wabbajack\\profiles\\erri120's Dope Test Modlist\\modlist.txt\"" + } + } +} \ No newline at end of file diff --git a/Wabbajack.CLI/Verbs/ChangeDownload.cs b/Wabbajack.CLI/Verbs/ChangeDownload.cs index f974d308..dc826a68 100644 --- a/Wabbajack.CLI/Verbs/ChangeDownload.cs +++ b/Wabbajack.CLI/Verbs/ChangeDownload.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -18,12 +17,15 @@ namespace Wabbajack.CLI.Verbs [Verb("change-download", HelpText = "Move or Copy all used Downloads from a Modlist to another directory")] public class ChangeDownload : AVerb { + [IsDirectory(Exit = true, CustomMessage = "Downloads folder %1 does not exist!")] [Option("input", Required = true, HelpText = "Input folder containing the downloads you want to move")] public string? Input { get; set; } + [IsDirectory(Create = true)] [Option("output", Required = true, HelpText = "Output folder the downloads should be transferred to")] public string? Output { get; set; } + [IsFile(Exit = true, CustomMessage = "Modlist file %1 does not exist!")] [Option("modlist", Required = true, HelpText = "The Modlist, can either be a .wabbajack or a modlist.txt file")] public string? Modlist { get; set; } @@ -58,17 +60,8 @@ namespace Wabbajack.CLI.Verbs protected override async Task Run() { - if (!File.Exists(Modlist)) - return CLIUtils.Exit($"The file {Modlist} does not exist!", -1); - - if (!Directory.Exists(Input)) - return CLIUtils.Exit($"The input directory {Input} does not exist!", -1); - - if (!Directory.Exists(Output)) - { - CLIUtils.Log($"The output directory {Output} does not exist, it will be created."); - Directory.CreateDirectory(Output); - } + if (!CLIUtils.HasValidArguments(this)) + CLIUtils.Exit("Arguments are not valid!", -1); if (Modlist != null && (!Modlist.EndsWith(Consts.ModListExtension) && !Modlist.EndsWith("modlist.txt"))) return CLIUtils.Exit($"The file {Modlist} is not a valid modlist file!", -1);