summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-09-08 18:17:09 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-09-08 18:17:09 -0400
commit5433f9023ed174366c8bf450785aafbdb077d29d (patch)
tree3a4fc71371d5a1194c2f819444aa7fc32f739830 /src
parent8a51279ce943ff74b45ec7af308ecf59d73ace9b (diff)
parentd53e033163cfc4a876d6a3341979315a3d937a4f (diff)
downloadSMAPI-5433f9023ed174366c8bf450785aafbdb077d29d.tar.gz
SMAPI-5433f9023ed174366c8bf450785aafbdb077d29d.tar.bz2
SMAPI-5433f9023ed174366c8bf450785aafbdb077d29d.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/manifest.json4
-rw-r--r--src/SMAPI.Mods.SaveBackup/manifest.json4
-rw-r--r--src/SMAPI.Tests/Toolkit/PathUtilitiesTests.cs70
-rw-r--r--src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs9
-rw-r--r--src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs2
-rw-r--r--src/SMAPI.Toolkit/Utilities/PathUtilities.cs41
-rw-r--r--src/SMAPI/Constants.cs2
-rw-r--r--src/SMAPI/Framework/Content/AssetDataForMap.cs2
-rw-r--r--src/SMAPI/Framework/Content/ContentCache.cs2
-rw-r--r--src/SMAPI/Framework/ContentPack.cs4
-rw-r--r--src/SMAPI/Framework/ModHelpers/DataHelper.cs4
-rw-r--r--src/SMAPI/Utilities/PathUtilities.cs6
12 files changed, 50 insertions, 100 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json
index c3560466..f15f3c57 100644
--- a/src/SMAPI.Mods.ConsoleCommands/manifest.json
+++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Console Commands",
"Author": "SMAPI",
- "Version": "3.7.1",
+ "Version": "3.7.2",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
- "MinimumApiVersion": "3.7.1"
+ "MinimumApiVersion": "3.7.2"
}
diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json
index 72e33fd1..c458feed 100644
--- a/src/SMAPI.Mods.SaveBackup/manifest.json
+++ b/src/SMAPI.Mods.SaveBackup/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Save Backup",
"Author": "SMAPI",
- "Version": "3.7.1",
+ "Version": "3.7.2",
"Description": "Automatically backs up all your saves once per day into its folder.",
"UniqueID": "SMAPI.SaveBackup",
"EntryDll": "SaveBackup.dll",
- "MinimumApiVersion": "3.7.1"
+ "MinimumApiVersion": "3.7.2"
}
diff --git a/src/SMAPI.Tests/Toolkit/PathUtilitiesTests.cs b/src/SMAPI.Tests/Toolkit/PathUtilitiesTests.cs
deleted file mode 100644
index 55785bfa..00000000
--- a/src/SMAPI.Tests/Toolkit/PathUtilitiesTests.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using NUnit.Framework;
-using StardewModdingAPI.Toolkit.Utilities;
-
-namespace SMAPI.Tests.Toolkit
-{
- /// <summary>Unit tests for <see cref="PathUtilities"/>.</summary>
- [TestFixture]
- public class PathUtilitiesTests
- {
- /*********
- ** Unit tests
- *********/
- [Test(Description = "Assert that GetSegments returns the expected values.")]
- [TestCase("", ExpectedResult = "")]
- [TestCase("/", ExpectedResult = "")]
- [TestCase("///", ExpectedResult = "")]
- [TestCase("/usr/bin", ExpectedResult = "usr|bin")]
- [TestCase("/usr//bin//", ExpectedResult = "usr|bin")]
- [TestCase("/usr//bin//.././boop.exe", ExpectedResult = "usr|bin|..|.|boop.exe")]
- [TestCase(@"C:", ExpectedResult = "C:")]
- [TestCase(@"C:/boop", ExpectedResult = "C:|boop")]
- [TestCase(@"C:\boop\/usr//bin//.././boop.exe", ExpectedResult = "C:|boop|usr|bin|..|.|boop.exe")]
- public string GetSegments(string path)
- {
- return string.Join("|", PathUtilities.GetSegments(path));
- }
-
- [Test(Description = "Assert that NormalizePathSeparators returns the expected values.")]
-#if SMAPI_FOR_WINDOWS
- [TestCase("", ExpectedResult = "")]
- [TestCase("/", ExpectedResult = "")]
- [TestCase("///", ExpectedResult = "")]
- [TestCase("/usr/bin", ExpectedResult = @"usr\bin")]
- [TestCase("/usr//bin//", ExpectedResult = @"usr\bin")]
- [TestCase("/usr//bin//.././boop.exe", ExpectedResult = @"usr\bin\..\.\boop.exe")]
- [TestCase("C:", ExpectedResult = "C:")]
- [TestCase("C:/boop", ExpectedResult = @"C:\boop")]
- [TestCase(@"C:\usr\bin//.././boop.exe", ExpectedResult = @"C:\usr\bin\..\.\boop.exe")]
-#else
- [TestCase("", ExpectedResult = "")]
- [TestCase("/", ExpectedResult = "/")]
- [TestCase("///", ExpectedResult = "/")]
- [TestCase("/usr/bin", ExpectedResult = "/usr/bin")]
- [TestCase("/usr//bin//", ExpectedResult = "/usr/bin")]
- [TestCase("/usr//bin//.././boop.exe", ExpectedResult = "/usr/bin/.././boop.exe")]
- [TestCase("C:", ExpectedResult = "C:")]
- [TestCase("C:/boop", ExpectedResult = "C:/boop")]
- [TestCase(@"C:\usr\bin//.././boop.exe", ExpectedResult = "C:/usr/bin/.././boop.exe")]
-#endif
- public string NormalizePathSeparators(string path)
- {
- return PathUtilities.NormalizePathSeparators(path);
- }
-
- [Test(Description = "Assert that GetRelativePath returns the expected values.")]
-#if SMAPI_FOR_WINDOWS
- [TestCase(@"C:\", @"C:\", ExpectedResult = "./")]
- [TestCase(@"C:\grandparent\parent\child", @"C:\grandparent\parent\sibling", ExpectedResult = @"..\sibling")]
- [TestCase(@"C:\grandparent\parent\child", @"C:\cousin\file.exe", ExpectedResult = @"..\..\..\cousin\file.exe")]
-#else
- [TestCase("/", "/", ExpectedResult = "./")]
- [TestCase("/grandparent/parent/child", "/grandparent/parent/sibling", ExpectedResult = "../sibling")]
- [TestCase("/grandparent/parent/child", "/cousin/file.exe", ExpectedResult = "../../../cousin/file.exe")]
-#endif
- public string GetRelativePath(string sourceDir, string targetPath)
- {
- return PathUtilities.GetRelativePath(sourceDir, targetPath);
- }
- }
-}
diff --git a/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs b/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs
index ea69a9ea..b5494003 100644
--- a/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs
+++ b/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs
@@ -179,10 +179,10 @@ namespace SMAPI.Tests.Utilities
****/
[Test(Description = "Assert that PathUtilities.NormalizePathSeparators normalizes paths correctly.")]
[TestCaseSource(nameof(PathUtilitiesTests.SamplePaths))]
- public void NormalizePathSeparators(SamplePath path)
+ public void NormalizePath(SamplePath path)
{
// act
- string normalized = PathUtilities.NormalizePathSeparators(path.OriginalPath);
+ string normalized = PathUtilities.NormalizePath(path.OriginalPath);
// assert
#if SMAPI_FOR_WINDOWS
@@ -218,11 +218,6 @@ namespace SMAPI.Tests.Utilities
ExpectedResult = @"path\to\child"
)]
[TestCase(
- @"\\parent\unc",
- @"\\adjacent\unc",
- ExpectedResult = @"\\adjacent\unc"
- )]
- [TestCase(
@"C:\same\path",
@"C:\same\path",
ExpectedResult = @"."
diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
index 450d600a..825988a5 100644
--- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
+++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
@@ -29,7 +29,7 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
IEnumerable<string> paths = this
.GetCustomInstallPaths(platform)
.Concat(this.GetDefaultInstallPaths(platform))
- .Select(PathUtilities.NormalizePathSeparators)
+ .Select(PathUtilities.NormalizePath)
.Distinct(StringComparer.OrdinalIgnoreCase);
// yield valid folders
diff --git a/src/SMAPI.Toolkit/Utilities/PathUtilities.cs b/src/SMAPI.Toolkit/Utilities/PathUtilities.cs
index bd5fafbc..c9fb6213 100644
--- a/src/SMAPI.Toolkit/Utilities/PathUtilities.cs
+++ b/src/SMAPI.Toolkit/Utilities/PathUtilities.cs
@@ -23,7 +23,7 @@ namespace StardewModdingAPI.Toolkit.Utilities
public static readonly char[] PossiblePathSeparators = new[] { '/', '\\', Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }.Distinct().ToArray();
/// <summary>The preferred directory separator character in an asset key.</summary>
- public static readonly string PreferredPathSeparator = Path.DirectorySeparatorChar.ToString();
+ public static readonly char PreferredPathSeparator = Path.DirectorySeparatorChar;
/*********
@@ -40,15 +40,37 @@ namespace StardewModdingAPI.Toolkit.Utilities
: path.Split(PathUtilities.PossiblePathSeparators, StringSplitOptions.RemoveEmptyEntries);
}
- /// <summary>Normalize path separators in a file path.</summary>
+ /// <summary>Normalize separators in a file path.</summary>
/// <param name="path">The file path to normalize.</param>
[Pure]
- public static string NormalizePathSeparators(string path)
+ public static string NormalizePath(string path)
{
- if (string.IsNullOrWhiteSpace(path))
+ path = path?.Trim();
+ if (string.IsNullOrEmpty(path))
return path;
- return string.Join(PathUtilities.PreferredPathSeparator, path.Split(PathUtilities.PossiblePathSeparators));
+ // get basic path format (e.g. /some/asset\\path/ => some\asset\path)
+ string[] segments = PathUtilities.GetSegments(path);
+ string newPath = string.Join(PathUtilities.PreferredPathSeparator.ToString(), segments);
+
+ // keep root prefix
+ bool hasRoot = false;
+ if (path.StartsWith(PathUtilities.WindowsUncRoot))
+ {
+ newPath = PathUtilities.WindowsUncRoot + newPath;
+ hasRoot = true;
+ }
+ else if (PathUtilities.PossiblePathSeparators.Contains(path[0]))
+ {
+ newPath = PathUtilities.PreferredPathSeparator + newPath;
+ hasRoot = true;
+ }
+
+ // keep trailing separator
+ if ((!hasRoot || segments.Any()) && PathUtilities.PossiblePathSeparators.Contains(path[path.Length - 1]))
+ newPath += PathUtilities.PreferredPathSeparator;
+
+ return newPath;
}
/// <summary>Get a directory or file path relative to a given source path. If no relative path is possible (e.g. the paths are on different drives), an absolute path is returned.</summary>
@@ -69,7 +91,10 @@ namespace StardewModdingAPI.Toolkit.Utilities
throw new InvalidOperationException($"Can't get path for '{targetPath}' relative to '{sourceDir}'.");
// get relative path
- string relative = PathUtilities.NormalizePathSeparators(Uri.UnescapeDataString(from.MakeRelativeUri(to).ToString()));
+ string rawUrl = Uri.UnescapeDataString(from.MakeRelativeUri(to).ToString());
+ if (rawUrl.StartsWith("file://"))
+ rawUrl = PathUtilities.WindowsUncRoot + rawUrl.Substring("file://".Length);
+ string relative = PathUtilities.NormalizePath(rawUrl);
// normalize
if (relative == "")
@@ -77,8 +102,8 @@ namespace StardewModdingAPI.Toolkit.Utilities
else
{
// trim trailing slash from URL
- if (relative.EndsWith(PathUtilities.PreferredPathSeparator))
- relative = relative.Substring(0, relative.Length - PathUtilities.PreferredPathSeparator.Length);
+ if (relative.EndsWith(PathUtilities.PreferredPathSeparator.ToString()))
+ relative = relative.Substring(0, relative.Length - 1);
// fix root
if (relative.StartsWith("file:") && !targetPath.Contains("file:"))
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 7540061d..6017a1d4 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -51,7 +51,7 @@ namespace StardewModdingAPI
** Public
****/
/// <summary>SMAPI's current semantic version.</summary>
- public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.7.1");
+ public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.7.2");
/// <summary>The minimum supported version of Stardew Valley.</summary>
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.4.1");
diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs
index e80c6e53..20f0ed0f 100644
--- a/src/SMAPI/Framework/Content/AssetDataForMap.cs
+++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs
@@ -153,7 +153,7 @@ namespace StardewModdingAPI.Framework.Content
if (string.IsNullOrWhiteSpace(path))
return string.Empty;
- path = PathUtilities.NormalizePathSeparators(path.Trim());
+ path = PathUtilities.NormalizePath(path);
if (path.StartsWith($"Maps{PathUtilities.PreferredPathSeparator}", StringComparison.OrdinalIgnoreCase))
path = path.Substring($"Maps{PathUtilities.PreferredPathSeparator}".Length);
if (path.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
diff --git a/src/SMAPI/Framework/Content/ContentCache.cs b/src/SMAPI/Framework/Content/ContentCache.cs
index 2052f6bf..af65e07e 100644
--- a/src/SMAPI/Framework/Content/ContentCache.cs
+++ b/src/SMAPI/Framework/Content/ContentCache.cs
@@ -80,7 +80,7 @@ namespace StardewModdingAPI.Framework.Content
[Pure]
public string NormalizePathSeparators(string path)
{
- return PathUtilities.NormalizePathSeparators(path);
+ return PathUtilities.NormalizePath(path);
}
/// <summary>Normalize a cache key so it's consistent with the underlying cache.</summary>
diff --git a/src/SMAPI/Framework/ContentPack.cs b/src/SMAPI/Framework/ContentPack.cs
index 55c1a0b2..65abba5b 100644
--- a/src/SMAPI/Framework/ContentPack.cs
+++ b/src/SMAPI/Framework/ContentPack.cs
@@ -62,7 +62,7 @@ namespace StardewModdingAPI.Framework
{
this.AssertRelativePath(path, nameof(this.ReadJsonFile));
- path = Path.Combine(this.DirectoryPath, PathUtilities.NormalizePathSeparators(path));
+ path = Path.Combine(this.DirectoryPath, PathUtilities.NormalizePath(path));
return this.JsonHelper.ReadJsonFileIfExists(path, out TModel model)
? model
: null;
@@ -73,7 +73,7 @@ namespace StardewModdingAPI.Framework
{
this.AssertRelativePath(path, nameof(this.WriteJsonFile));
- path = Path.Combine(this.DirectoryPath, PathUtilities.NormalizePathSeparators(path));
+ path = Path.Combine(this.DirectoryPath, PathUtilities.NormalizePath(path));
this.JsonHelper.WriteJsonFile(path, data);
}
diff --git a/src/SMAPI/Framework/ModHelpers/DataHelper.cs b/src/SMAPI/Framework/ModHelpers/DataHelper.cs
index c232a6dd..41612387 100644
--- a/src/SMAPI/Framework/ModHelpers/DataHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/DataHelper.cs
@@ -45,7 +45,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
if (!PathUtilities.IsSafeRelativePath(path))
throw new InvalidOperationException($"You must call {nameof(IModHelper.Data)}.{nameof(this.ReadJsonFile)} with a relative path.");
- path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePathSeparators(path));
+ path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePath(path));
return this.JsonHelper.ReadJsonFileIfExists(path, out TModel data)
? data
: null;
@@ -57,7 +57,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
if (!PathUtilities.IsSafeRelativePath(path))
throw new InvalidOperationException($"You must call {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteJsonFile)} with a relative path (without directory climbing).");
- path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePathSeparators(path));
+ path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePath(path));
this.JsonHelper.WriteJsonFile(path, data);
}
diff --git a/src/SMAPI/Utilities/PathUtilities.cs b/src/SMAPI/Utilities/PathUtilities.cs
index ea134468..19f16ea9 100644
--- a/src/SMAPI/Utilities/PathUtilities.cs
+++ b/src/SMAPI/Utilities/PathUtilities.cs
@@ -18,12 +18,12 @@ namespace StardewModdingAPI.Utilities
return ToolkitPathUtilities.GetSegments(path, limit);
}
- /// <summary>Normalize path separators in a file path.</summary>
+ /// <summary>Normalize separators in a file path.</summary>
/// <param name="path">The file path to normalize.</param>
[Pure]
- public static string NormalizePathSeparators(string path)
+ public static string NormalizePath(string path)
{
- return ToolkitPathUtilities.NormalizePathSeparators(path);
+ return ToolkitPathUtilities.NormalizePath(path);
}
/// <summary>Get whether a path is relative and doesn't try to climb out of its containing folder (e.g. doesn't contain <c>../</c>).</summary>