8 Commits
1.3.1 ... 1.3.2

Author SHA1 Message Date
Matt Nadareski
f888cd4e57 Bump version 2024-03-12 16:27:56 -04:00
Matt Nadareski
04fc2dc96e Fix incorrect nullability check 2024-03-11 13:38:10 -04:00
Matt Nadareski
2371813175 Allow Ensure to take a null string 2024-03-11 13:35:34 -04:00
Matt Nadareski
99b3bb25f2 Make ParentablePath normalization clearer 2024-03-05 11:34:38 -05:00
Matt Nadareski
2ee40e341f Ensure paths are normalized on ParentablePath creation 2024-03-05 11:02:46 -05:00
Matt Nadareski
90ed6a9a65 Normalize paths to Windows for tests 2024-03-05 10:54:58 -05:00
Matt Nadareski
89e29c9cab Port tests from SabreTools 2024-03-05 10:45:31 -05:00
Matt Nadareski
1a6ff6d64f Move library to subfolder to prep for test additions 2024-03-05 10:40:45 -05:00
22 changed files with 178 additions and 9 deletions

View File

@@ -20,6 +20,12 @@ jobs:
- name: Restore dependencies
run: dotnet restore
- name: Build library
run: dotnet build
- name: Run tests
run: dotnet test
- name: Pack
run: dotnet pack
@@ -28,13 +34,13 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: 'Nuget Package'
path: 'bin/Release/*.nupkg'
path: 'SabreTools.IO/bin/Release/*.nupkg'
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: 'bin/Release/*.nupkg'
artifacts: 'SabreTools.IO/bin/Release/*.nupkg'
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True

View File

@@ -14,4 +14,7 @@ jobs:
dotnet-version: 8.0.x
- name: Build
run: dotnet build
run: dotnet build
- name: Run tests
run: dotnet test

View File

@@ -0,0 +1,23 @@
using Xunit;
namespace SabreTools.IO.Test
{
public class IOExtensionsTests
{
[Theory]
[InlineData(null, null)]
[InlineData("", null)]
[InlineData(" ", null)]
[InlineData("no-extension", null)]
[InlineData("NO-EXTENSION", null)]
[InlineData("no-extension.", null)]
[InlineData("NO-EXTENSION.", null)]
[InlineData("filename.ext", "ext")]
[InlineData("FILENAME.EXT", "ext")]
public void NormalizedExtensionTest(string? path, string? expected)
{
string? actual = path.GetNormalizedExtension();
Assert.Equal(expected, actual);
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using Xunit;
namespace SabreTools.IO.Test
{
public class ParentablePathTests
{
[Theory]
[InlineData("", null, false, null)]
[InlineData("", null, true, null)]
[InlineData(" ", null, false, null)]
[InlineData(" ", null, true, null)]
[InlineData("C:\\Directory\\Filename.ext", null, false, "Filename.ext")]
[InlineData("C:\\Directory\\Filename.ext", null, true, "Filename.ext")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", false, "Filename.ext")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", true, "Filename.ext")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", false, "SubDir\\Filename.ext")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", true, "SubDir-Filename.ext")]
public void NormalizedFileNameTest(string current, string? parent, bool sanitize, string? expected)
{
var path = new ParentablePath(current, parent);
string? actual = path.GetNormalizedFileName(sanitize);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData("", null, null, false, null)]
[InlineData("", null, null, true, null)]
[InlineData(" ", null, null, false, null)]
[InlineData(" ", null, null, true, null)]
[InlineData("C:\\Directory\\Filename.ext", null, null, false, null)]
[InlineData("C:\\Directory\\Filename.ext", null, null, true, "C:\\Directory")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", null, false, null)]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", null, true, "C:\\Directory")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", null, false, null)]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", null, true, "C:\\Directory\\SubDir")]
[InlineData("", null, "D:\\OutputDirectory", false, null)]
[InlineData("", null, "D:\\OutputDirectory", true, null)]
[InlineData(" ", null, "D:\\OutputDirectory", false, null)]
[InlineData(" ", null, "D:\\OutputDirectory", true, null)]
[InlineData("C:\\Directory\\Filename.ext", null, "D:\\OutputDirectory", false, "D:\\OutputDirectory")]
[InlineData("C:\\Directory\\Filename.ext", null, "D:\\OutputDirectory", true, "C:\\Directory")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", "D:\\OutputDirectory", false, "D:\\OutputDirectory")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", "D:\\OutputDirectory", true, "C:\\Directory")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", "D:\\OutputDirectory", false, "D:\\OutputDirectory\\SubDir")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", "D:\\OutputDirectory", true, "C:\\Directory\\SubDir")]
[InlineData("", null, "%cd%", false, null)]
[InlineData("", null, "%cd%", true, null)]
[InlineData(" ", null, "%cd%", false, null)]
[InlineData(" ", null, "%cd%", true, null)]
[InlineData("C:\\Directory\\Filename.ext", null, "%cd%", false, "%cd%")]
[InlineData("C:\\Directory\\Filename.ext", null, "%cd%", true, "C:\\Directory")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", "%cd%", false, "%cd%")]
[InlineData("C:\\Directory\\Filename.ext", "C:\\Directory\\Filename.ext", "%cd%", true, "C:\\Directory")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", "%cd%", false, "%cd%\\Directory\\SubDir")]
[InlineData("C:\\Directory\\SubDir\\Filename.ext", "C:\\Directory", "%cd%", true, "C:\\Directory\\SubDir")]
public void GetOutputPathTest(string current, string? parent, string? outDir, bool inplace, string? expected)
{
// Hacks because I can't use environment vars as parameters
if (outDir == "%cd%")
outDir = Environment.CurrentDirectory.TrimEnd('\\', '/');
if (expected?.Contains("%cd%") == true)
expected = expected.Replace("%cd%", Environment.CurrentDirectory.TrimEnd('\\', '/'));
var path = new ParentablePath(current, parent);
string? actual = path.GetOutputPath(outDir, inplace);
Assert.Equal(expected, actual);
}
}
}

View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SabreTools.IO\SabreTools.IO.csproj" />
</ItemGroup>
</Project>

View File

@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.IO", "SabreTools.IO.csproj", "{87CE4411-80D9-49FF-894C-761F1C20D9A5}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.IO", "SabreTools.IO\SabreTools.IO.csproj", "{87CE4411-80D9-49FF-894C-761F1C20D9A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.IO.Test", "SabreTools.IO.Test\SabreTools.IO.Test.csproj", "{A9767735-5042-48A1-849C-96035DB1DD53}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -18,5 +20,9 @@ Global
{87CE4411-80D9-49FF-894C-761F1C20D9A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87CE4411-80D9-49FF-894C-761F1C20D9A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87CE4411-80D9-49FF-894C-761F1C20D9A5}.Release|Any CPU.Build.0 = Release|Any CPU
{A9767735-5042-48A1-849C-96035DB1DD53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9767735-5042-48A1-849C-96035DB1DD53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9767735-5042-48A1-849C-96035DB1DD53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9767735-5042-48A1-849C-96035DB1DD53}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -16,14 +16,14 @@ namespace SabreTools.IO
/// <param name="dir">Directory to check</param>
/// <param name="create">True if the directory should be created, false otherwise (default)</param>
/// <returns>Full path to the directory</returns>
public static string Ensure(this string dir, bool create = false)
public static string Ensure(this string? dir, bool create = false)
{
// If the output directory is invalid
if (string.IsNullOrEmpty(dir))
dir = PathTool.GetRuntimeDirectory();
// Get the full path for the output directory
dir = Path.GetFullPath(dir.Trim('"'));
dir = Path.GetFullPath(dir!.Trim('"'));
// If we're creating the output folder, do so
if (create && !Directory.Exists(dir))

View File

@@ -39,7 +39,7 @@ namespace SabreTools.IO
string filename = Path.GetFileName(CurrentPath);
// If we have a true ParentPath, remove it from CurrentPath and return the remainder
if (!string.IsNullOrEmpty(ParentPath) && !string.Equals(CurrentPath, ParentPath, StringComparison.Ordinal))
if (!string.IsNullOrEmpty(ParentPath) && !PathsEqual(CurrentPath, ParentPath))
filename = CurrentPath.Remove(0, ParentPath!.Length + 1);
// If we're sanitizing the path after, do so
@@ -92,5 +92,39 @@ namespace SabreTools.IO
return Path.GetDirectoryName(Path.Combine(outDir!, CurrentPath.Remove(0, workingParent.Length + extraLength)));
}
/// <summary>
/// Determine if two paths are equal or not
/// </summary>
private static bool PathsEqual(string? path1, string? path2, bool caseSenstive = false)
{
// Handle null path cases
if (path1 == null && path2 == null)
return true;
else if (path1 == null ^ path2 == null)
return false;
// Normalize the paths before comparing
path1 = NormalizeDirectorySeparators(path1);
path2 = NormalizeDirectorySeparators(path2);
// Compare and return
return string.Equals(path1, path2, caseSenstive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Normalize directory separators for the current system
/// </summary>
/// <param name="input">Input path that may contain separators</param>
/// <returns>Normalized path with separators fixed, if possible</returns>
private static string? NormalizeDirectorySeparators(string? input)
{
// Null inputs are skipped
if (input == null)
return null;
// Replace alternate directory separators with the correct one
return input.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
}
}
}

View File

@@ -7,7 +7,7 @@
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.3.1</Version>
<Version>1.3.2</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
@@ -22,7 +22,7 @@
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath=""/>
<None Include="../README.md" Pack="true" PackagePath=""/>
</ItemGroup>
<!-- Support for old .NET versions -->