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);