Skip to content

Commit abce4b1

Browse files
committed
Refactor path handling to use platform-specific separators
ModPaths and AdditionalFallbackPath are now single string properties using the platform-specific path separator, instead of IList<string>. SettingsBuilder splits and normalizes these paths accordingly. Help texts are updated, and unit tests are added to verify correct path parsing and normalization using a mock file system.
1 parent 7a7f2d3 commit abce4b1

3 files changed

Lines changed: 71 additions & 25 deletions

File tree

src/ModVerify.CliApp/Settings/CommandLine/BaseModVerifyOptions.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ internal abstract class BaseModVerifyOptions
2525
"The argument cannot be combined with any of --mods, --game or --fallbackGame")]
2626
public string? TargetPath { get; init; }
2727

28-
[Option("mods", SetName = "manualPaths", Required = false, Default = null, Separator = ';',
29-
HelpText = "The path of the mod to verify. To support submods, multiple paths can be separated using the ';' (semicolon) character. " +
28+
[Option("mods", SetName = "manualPaths", Required = false, Default = null,
29+
HelpText = "The path of the mod to verify. To support submods, multiple paths can be separated using the platform-specific path separator (';' on Windows, ':' on Linux). " +
3030
"Leave empty, if you want to verify a game. If you want to use the interactive mode, leave this, --game and --fallbackGame empty.")]
31-
public IList<string>? ModPaths { get; init; }
31+
public string? ModPaths { get; init; }
3232

3333
[Option("game", SetName = "manualPaths", Required = false, Default = null,
3434
HelpText = "The path of the base game. For FoC mods this points to the FoC installation, for EaW mods this points to the EaW installation. " +
@@ -47,10 +47,10 @@ internal abstract class BaseModVerifyOptions
4747
public GameEngineType? Engine { get; init; }
4848

4949

50-
[Option("additionalFallbackPaths", Required = false, Separator = ';',
50+
[Option("additionalFallbackPaths", Required = false,
5151
HelpText = "Additional fallback paths, which may contain assets that shall be included when doing the verification. Do not add EaW here. " +
52-
"Multiple paths can be separated using the ';' (semicolon) character.")]
53-
public IList<string>? AdditionalFallbackPath { get; init; }
52+
"Multiple paths can be separated using the platform-specific path separator (';' on Windows, ':' on Linux).")]
53+
public string? AdditionalFallbackPath { get; init; }
5454

5555
[Option("parallel", Default = false,
5656
HelpText = "When set, game verifiers will run in parallel. " +

src/ModVerify.CliApp/Settings/SettingsBuilder.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.IO.Abstractions;
7+
using System.Linq;
78

89
namespace AET.ModVerify.App.Settings;
910

@@ -136,24 +137,20 @@ AppReportSettings BuildReportSettings()
136137

137138
private VerificationTargetSettings BuildTargetSettings(BaseModVerifyOptions options)
138139
{
140+
var separator = _fileSystem.Path.PathSeparator;
141+
139142
var modPaths = new List<string>();
140-
if (options.ModPaths is not null)
143+
if (!string.IsNullOrEmpty(options.ModPaths))
141144
{
142-
foreach (var mod in options.ModPaths)
143-
{
144-
if (!string.IsNullOrEmpty(mod))
145-
modPaths.Add(_fileSystem.Path.GetFullPath(mod));
146-
}
145+
var split = options.ModPaths!.Split([separator], StringSplitOptions.RemoveEmptyEntries);
146+
modPaths.AddRange(split.Select(s => _fileSystem.Path.GetFullPath(s)));
147147
}
148148

149149
var fallbackPaths = new List<string>();
150-
if (options.AdditionalFallbackPath is not null)
150+
if (!string.IsNullOrEmpty(options.AdditionalFallbackPath))
151151
{
152-
foreach (var fallback in options.AdditionalFallbackPath)
153-
{
154-
if (!string.IsNullOrEmpty(fallback))
155-
fallbackPaths.Add(_fileSystem.Path.GetFullPath(fallback));
156-
}
152+
var split = options.AdditionalFallbackPath!.Split([separator], StringSplitOptions.RemoveEmptyEntries);
153+
fallbackPaths.AddRange(split.Select(s => _fileSystem.Path.GetFullPath(s)));
157154
}
158155

159156
var gamePath = options.GamePath;

test/ModVerify.CliApp.Test/SettingsBuilderTest.cs

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,72 @@
11
using AET.ModVerify.App;
22
using AET.ModVerify.App.Settings;
33
using AET.ModVerify.App.Settings.CommandLine;
4-
using Microsoft.Extensions.DependencyInjection;
54
using System.IO.Abstractions;
6-
using Testably.Abstractions;
5+
using Testably.Abstractions.Testing;
76
using Xunit;
7+
using AnakinRaW.CommonUtilities.Testing;
88

99
namespace ModVerify.CliApp.Test;
1010

11-
public class SettingsBuilderTest
11+
public class SettingsBuilderTest : TestBaseWithFileSystem
1212
{
1313
private readonly SettingsBuilder _builder;
1414

1515
public SettingsBuilderTest()
1616
{
17-
var services = new ServiceCollection();
18-
services.AddSingleton<IFileSystem>(new RealFileSystem());
19-
var provider = services.BuildServiceProvider();
20-
_builder = new SettingsBuilder(provider);
17+
_builder = new SettingsBuilder(ServiceProvider);
18+
}
19+
20+
protected override IFileSystem CreateFileSystem()
21+
{
22+
return new MockFileSystem();
23+
}
24+
25+
[Theory]
26+
[InlineData("path1", "path2")]
27+
public void BuildSettings_Paths_SplitsCorrectly(string p1, string p2)
28+
{
29+
var separator = FileSystem.Path.PathSeparator;
30+
var paths = $"{p1}{separator}{p2}";
31+
var expected = new[] { FileSystem.Path.GetFullPath(p1), FileSystem.Path.GetFullPath(p2) };
32+
33+
var options = new VerifyVerbOption
34+
{
35+
ModPaths = paths,
36+
AdditionalFallbackPath = paths,
37+
TargetPath = "myPath"
38+
};
39+
40+
var settings = _builder.BuildSettings(options);
41+
42+
Assert.Equal(expected, settings.VerificationTargetSettings.ModPaths);
43+
Assert.Equal(expected, settings.VerificationTargetSettings.AdditionalFallbackPaths);
44+
}
45+
46+
[Fact]
47+
public void BuildSettings_FallbackGamePath_RequiresGamePath()
48+
{
49+
var gamePath = "game";
50+
var fallbackPath = "fallback";
51+
52+
var options = new VerifyVerbOption
53+
{
54+
GamePath = gamePath,
55+
FallbackGamePath = fallbackPath,
56+
TargetPath = "myPath"
57+
};
58+
59+
var settings = _builder.BuildSettings(options);
60+
Assert.Equal(FileSystem.Path.GetFullPath(fallbackPath), settings.VerificationTargetSettings.FallbackGamePath);
61+
62+
var optionsNoGame = new VerifyVerbOption
63+
{
64+
FallbackGamePath = fallbackPath,
65+
TargetPath = "myPath"
66+
};
67+
68+
var settingsNoGame = _builder.BuildSettings(optionsNoGame);
69+
Assert.Null(settingsNoGame.VerificationTargetSettings.FallbackGamePath);
2170
}
2271

2372
[Fact]

0 commit comments

Comments
 (0)