rename PathUtilities.NormalizePathSeparator, add normalization for more cases
This commit is contained in:
parent
8a51279ce9
commit
7580f87029
|
@ -7,6 +7,13 @@
|
|||
* Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
|
||||
-->
|
||||
|
||||
## Upcoming release
|
||||
* For players:
|
||||
* Fixed mod recipe changes not always applied in 3.7.
|
||||
|
||||
* For modders:
|
||||
* Renamed `PathUtilities.NormalizePathSeparators` to `NormalizePath`, and added normalization for more cases.
|
||||
|
||||
## 3.7.1
|
||||
Released 08 September 2020 for Stardew Valley 1.4.1 or later.
|
||||
|
||||
|
|
|
@ -47,9 +47,9 @@ namespace SMAPI.Tests.Toolkit
|
|||
[TestCase("C:/boop", ExpectedResult = "C:/boop")]
|
||||
[TestCase(@"C:\usr\bin//.././boop.exe", ExpectedResult = "C:/usr/bin/.././boop.exe")]
|
||||
#endif
|
||||
public string NormalizePathSeparators(string path)
|
||||
public string NormalizePath(string path)
|
||||
{
|
||||
return PathUtilities.NormalizePathSeparators(path);
|
||||
return PathUtilities.NormalizePath(path);
|
||||
}
|
||||
|
||||
[Test(Description = "Assert that GetRelativePath returns the expected values.")]
|
||||
|
|
|
@ -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
|
||||
|
@ -217,11 +217,6 @@ namespace SMAPI.Tests.Utilities
|
|||
@"\\parent\unc\path\to\child",
|
||||
ExpectedResult = @"path\to\child"
|
||||
)]
|
||||
[TestCase(
|
||||
@"\\parent\unc",
|
||||
@"\\adjacent\unc",
|
||||
ExpectedResult = @"\\adjacent\unc"
|
||||
)]
|
||||
[TestCase(
|
||||
@"C:\same\path",
|
||||
@"C:\same\path",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:"))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue