diff --git a/SabreTools.IO/ParentablePath.cs b/SabreTools.IO/ParentablePath.cs index 7fb4616d..5aa5e82f 100644 --- a/SabreTools.IO/ParentablePath.cs +++ b/SabreTools.IO/ParentablePath.cs @@ -31,6 +31,10 @@ namespace SabreTools.IO /// Subpath for the file public string GetNormalizedFileName(bool sanitize) { + // If the current path is empty, we can't do anything + if (string.IsNullOrWhiteSpace(CurrentPath)) + return null; + // Check that we have a combined path first if (string.IsNullOrWhiteSpace(ParentPath)) { @@ -70,8 +74,13 @@ namespace SabreTools.IO /// Complete output path public string GetOutputPath(string outDir, bool inplace) { - // First, we need to ensure the output directory - outDir = outDir.Ensure(); + // If the current path is empty, we can't do anything + if (string.IsNullOrWhiteSpace(CurrentPath)) + return null; + + // If the output dir is empty (and we're not inplace), we can't do anything + if (string.IsNullOrWhiteSpace(outDir) && !inplace) + return null; // Check if we have a split path or not bool splitpath = !string.IsNullOrWhiteSpace(ParentPath); @@ -89,13 +98,20 @@ namespace SabreTools.IO // If we are processing a path that is coming from a directory and we are outputting to the current directory, we want to get the subfolder to write to else if (CurrentPath.Length != ParentPath.Length && outDir == Environment.CurrentDirectory) { - outDir = Path.GetDirectoryName(Path.Combine(outDir, CurrentPath.Remove(0, Path.GetDirectoryName(ParentPath).Length + 1))); + string nextDir = Path.GetDirectoryName(ParentPath); + int extraLength = nextDir.EndsWith(':') + || nextDir.EndsWith(Path.DirectorySeparatorChar) + || nextDir.EndsWith(Path.AltDirectorySeparatorChar) ? 0 : 1; + outDir = Path.GetDirectoryName(Path.Combine(outDir, CurrentPath.Remove(0, nextDir.Length + extraLength))); } // If we are processing a path that is coming from a directory, we want to get the subfolder to write to else if (CurrentPath.Length != ParentPath.Length) { - outDir = Path.GetDirectoryName(Path.Combine(outDir, CurrentPath.Remove(0, ParentPath.Length + 1))); + int extraLength = ParentPath.EndsWith(':') + || ParentPath.EndsWith(Path.DirectorySeparatorChar) + || ParentPath.EndsWith(Path.AltDirectorySeparatorChar) ? 0 : 1; + outDir = Path.GetDirectoryName(Path.Combine(outDir, CurrentPath.Remove(0, ParentPath.Length + extraLength))); } // If we are processing a single file from the root of a directory, we just use the output directory diff --git a/SabreTools.Test/IO/ParentablePathTests.cs b/SabreTools.Test/IO/ParentablePathTests.cs new file mode 100644 index 00000000..843a23b0 --- /dev/null +++ b/SabreTools.Test/IO/ParentablePathTests.cs @@ -0,0 +1,80 @@ +using System; + +using SabreTools.IO; +using Xunit; + +namespace SabreTools.Test.IO +{ + public class ParentablePathTests + { + [Theory] + [InlineData(null, null, false, null)] + [InlineData(null, null, true, null)] + [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, null, false, null)] + [InlineData(null, null, null, true, null)] + [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, null, "D:\\OutputDirectory", false, null)] + [InlineData(null, null, "D:\\OutputDirectory", true, null)] + [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, null, "%cd%", false, null)] + [InlineData(null, null, "%cd%", true, null)] + [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); + } + } +} \ No newline at end of file diff --git a/SabreTools.Test/SabreTools.Test.csproj b/SabreTools.Test/SabreTools.Test.csproj index 7c6a49ee..b1017c22 100644 --- a/SabreTools.Test/SabreTools.Test.csproj +++ b/SabreTools.Test/SabreTools.Test.csproj @@ -7,6 +7,7 @@ + diff --git a/SabreTools/Features/Split.cs b/SabreTools/Features/Split.cs index 796e9cc2..1d67fc29 100644 --- a/SabreTools/Features/Split.cs +++ b/SabreTools/Features/Split.cs @@ -59,6 +59,7 @@ namespace SabreTools.Features Parser.ParseInto(internalDat, file); // Get the output directory + OutputDir = OutputDir.Ensure(); OutputDir = file.GetOutputPath(OutputDir, GetBoolean(features, InplaceValue)); // Extension splitting diff --git a/SabreTools/Features/Update.cs b/SabreTools/Features/Update.cs index a1e15734..bcd201e5 100644 --- a/SabreTools/Features/Update.cs +++ b/SabreTools/Features/Update.cs @@ -138,6 +138,9 @@ namespace SabreTools.Features List inputPaths = PathTool.GetFilesOnly(Inputs, appendparent: true); List basePaths = PathTool.GetFilesOnly(GetList(features, BaseDatListValue)); + // Ensure the output directory + OutputDir = OutputDir.Ensure(); + // If we're in standard update mode, run through all of the inputs if (updateMode == UpdateMode.None) {