Skip to content

Commit 821e5b3

Browse files
committed
Merge branch 'feat/support-linux' of https://github.com/AlamoEngine-Tools/ModVerify into feat/support-linux
2 parents 71f7742 + df19dee commit 821e5b3

4 files changed

Lines changed: 100 additions & 5 deletions

File tree

.github/workflows/release.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ jobs:
4747
- name: Create Net Core Release
4848
# use publish for .NET Core
4949
run: dotnet publish ${{ env.TOOL_PROJ_PATH }} --configuration Release -f net10.0 --output ./releases/net10.0 /p:DebugType=None /p:DebugSymbols=false
50+
- name: Create Linux Release
51+
run: dotnet publish ${{ env.TOOL_PROJ_PATH }} --configuration Release -f net10.0 --runtime linux-x64 --self-contained true --output ./releases/linux-x64 /p:DebugType=None /p:DebugSymbols=false
5052
- name: Upload a Build Artifact
5153
uses: actions/upload-artifact@v7
5254
with:
@@ -117,4 +119,5 @@ jobs:
117119
generate_release_notes: true
118120
files: |
119121
./releases/net481/ModVerify.exe
120-
./releases/ModVerify-Net10.zip
122+
./releases/ModVerify-Net10.zip
123+
./releases/linux-x64/ModVerify

README.md

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,42 @@ In general ModVerify has two operation mods.
8080
1. `verify` Verifying a game or mod
8181
2. `createBaseline` Creating a baseline for a game or mod, that can be used for further verifications in order to verify you did not add more errors to your mods.
8282

83-
### Example
84-
This is an example run configuration that analyzes a specific mod, uses a the FoC basline and writes the output into a dedicated directory:
83+
### Examples
8584

86-
```bash
85+
#### Example 1: Auto-detection with a custom baseline
86+
Analyzes a specific mod, uses the FoC baseline and writes the output into a dedicated directory:
87+
88+
**Windows:**
89+
```bat
8790
.\ModVerify.exe verify --path "C:\My Games\FoC\Mods\MyMod" --outDir "C:\My Games\FoC\Mods\MyMod\verifyResults" --baseline ./focBaseline.json
8891
```
8992

93+
**Linux:**
94+
```bash
95+
./ModVerify verify \
96+
--path "/home/user/games/FoC/Mods/MyMod" \
97+
--outDir "/home/user/games/FoC/Mods/MyMod/verifyResults" \
98+
--baseline ./focBaseline.json
99+
```
100+
101+
#### Example 2: Manual mod setup with sub-mods, EaW fallback and default baseline
102+
Uses manual mod setup, including sub-mods and the EaW fallback game, and uses the default embedded baseline:
103+
104+
**Windows:**
105+
```bat
106+
.\ModVerify.exe verify --mods "C:\My Games\FoC\Mods\MySubMod;C:\My Games\FoC\Mods\MyMod" --game "C:\My Games\FoC" --fallbackGame "C:\My Games\EaW" --engine FOC --useDefaultBaseline
107+
```
108+
109+
**Linux:**
110+
```bash
111+
./ModVerify verify \
112+
--mods "/home/user/games/FoC/Mods/MySubMod:/home/user/games/FoC/Mods/MyMod" \
113+
--game "/home/user/games/FoC" \
114+
--fallbackGame "/home/user/games/EaW" \
115+
--engine FOC \
116+
--useDefaultBaseline
117+
```
118+
90119
---
91120

92121
## Available Checks
@@ -116,6 +145,14 @@ The following verifiers are currently implemented:
116145
If you want to create your own baseline use the `createBaseline` option.
117146

118147
### Example
148+
149+
**Windows**
119150
```bash
120151
ModVerify.exe createBaseline --outFile myBaseline.json --path "C:\My Games\FoC\Mods\MyMod"
121152
```
153+
**Linux**
154+
```bash
155+
./ModVerify createBaseline \
156+
--outFile myBaseline.json \
157+
--path "C:\My Games\FoC\Mods\MyMod"
158+
```

src/PetroglyphTools/PG.StarWarsGame.Engine.FileSystem.Test/IO/PetroglyphFileSystemTests.Exist.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.IO;
33
using System.Runtime.InteropServices;
4+
using AnakinRaW.CommonUtilities.Testing.Attributes;
45
using PG.StarWarsGame.Engine.Utilities;
56
using Xunit;
67

@@ -84,6 +85,8 @@ public void FileExists_RelativePath()
8485
[InlineData("a/b/c.txt", "A/B/C.txt")]
8586
[InlineData("A/B/C.txt", "a/b/c.txt")]
8687
[InlineData("a/B/c.txt", "A/b/C.txt")]
88+
[InlineData("a/B/C.txt", "a/B/c.txt")]
89+
[InlineData("a/b/C/D.txt", "a/b/c/d.txt")]
8790
public void FileExists_CaseInsensitive(string inputPath, string actualPathOnDisk)
8891
{
8992
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
@@ -148,6 +151,58 @@ public void FileExists_GameDirectory_WithTrailingSeparator()
148151
}
149152
}
150153

154+
[PlatformSpecificFact(TestPlatformIdentifier.Linux)]
155+
public void FileExists_CaseInsensitive_DotSegmentInPath_ReturnsTrue()
156+
{
157+
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
158+
Directory.CreateDirectory(tempDir);
159+
160+
try
161+
{
162+
// Create the actual file at tempDir/DATA/FILE.TXT (uppercase)
163+
Directory.CreateDirectory(Path.Combine(tempDir, "DATA"));
164+
File.WriteAllText(Path.Combine(tempDir, "DATA", "FILE.TXT"), "test");
165+
166+
// Input path uses a leading ".\" (dot-segment) AND different casing.
167+
// After normalization + join: tempDir/./DATA/file.txt
168+
// File.Exists fast-path fails (case mismatch), so the impl must resolve case-insensitively.
169+
// Correct impls must handle "." as a valid path segment that resolves to the current directory,
170+
// not treat it as a literal directory name to look up via GetDirectories.
171+
var vsb = new ValueStringBuilder();
172+
var exists = _pgFileSystem.FileExists(@".\DATA\file.txt".AsSpan(), ref vsb, tempDir.AsSpan());
173+
174+
Assert.True(exists);
175+
}
176+
finally
177+
{
178+
Directory.Delete(tempDir, true);
179+
}
180+
}
181+
182+
[PlatformSpecificFact(TestPlatformIdentifier.Linux)]
183+
public void FileExists_CaseInsensitive_MissingIntermediateDirectory_ReturnsFalse()
184+
{
185+
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
186+
Directory.CreateDirectory(tempDir);
187+
188+
try
189+
{
190+
// Create tempDir/a/c.txt — no "b" directory at all
191+
Directory.CreateDirectory(Path.Combine(tempDir, "a"));
192+
File.WriteAllText(Path.Combine(tempDir, "a", "c.txt"), "test");
193+
194+
// Input path references a non-existent intermediate segment "b"
195+
var vsb = new ValueStringBuilder();
196+
var exists = _pgFileSystem.FileExists("a/b/c.txt".AsSpan(), ref vsb, tempDir.AsSpan());
197+
198+
Assert.False(exists);
199+
}
200+
finally
201+
{
202+
Directory.Delete(tempDir, true);
203+
}
204+
}
205+
151206
[Theory]
152207
#if Windows
153208
[InlineData("C:\\test.txt", true)]

src/PetroglyphTools/PG.StarWarsGame.Engine.FileSystem/IO/PetroglyphFileSystem.Exist.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ private bool FileExistsCaseInsensitive(ReadOnlySpan<char> filePath, ref ValueStr
100100

101101
return false;
102102
}
103-
103+
104104
private bool IsPathFullyQualified_Exists(ReadOnlySpan<char> path)
105105
{
106106
// This is really tricky, because under Windows "/" or "\" do NOT

0 commit comments

Comments
 (0)