From 8c53a06a6bc83de596761848f4edc2018a5317a4 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 17 Aug 2019 16:03:27 +1000 Subject: [PATCH] Port GetRelativePath --- BizHawk.Client.Common/PathManager.cs | 2 +- .../MultiDiskBundler/MultiDiskBundler.cs | 63 +++++++++++++++---- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/BizHawk.Client.Common/PathManager.cs b/BizHawk.Client.Common/PathManager.cs index f7f0911765..91c6b1a53a 100644 --- a/BizHawk.Client.Common/PathManager.cs +++ b/BizHawk.Client.Common/PathManager.cs @@ -439,7 +439,7 @@ namespace BizHawk.Client.Common } /// Algorithm for Windows taken from https://stackoverflow.com/a/7710620/7467292 - private static bool IsSubfolder(string parentPath, string childPath) + public static bool IsSubfolder(string parentPath, string childPath) { if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows) { diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs index 4ea575c4b2..3a0dc74500 100644 --- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs +++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs @@ -12,6 +12,7 @@ using System.Xml.Linq; using BizHawk.Emulation.Common; using BizHawk.Client.Common; using BizHawk.Client.EmuHawk.WinFormExtensions; +using BizHawk.Common; namespace BizHawk.Client.EmuHawk { @@ -277,26 +278,62 @@ namespace BizHawk.Client.EmuHawk } } - // http://stackoverflow.com/questions/275689/how-to-get-relative-path-from-absolute-path + /// Algorithm for Windows taken from https://stackoverflow.com/a/485516/7467292 public static string GetRelativePath(string fromPath, string toPath) { - Win32.FileAttributes fromAttr = GetPathAttribute(fromPath); - Win32.FileAttributes toAttr = GetPathAttribute(toPath); - - var path = new StringBuilder(260); // MAX_PATH - if (Win32.PathRelativePathTo( - path, - fromPath, - fromAttr, - toPath, - toAttr) == false) + if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows) { - throw new ArgumentException("Paths must have a common prefix"); + Win32.FileAttributes fromAttr = GetPathAttribute(fromPath); + Win32.FileAttributes toAttr = GetPathAttribute(toPath); + + var path = new StringBuilder(260); // MAX_PATH + if (Win32.PathRelativePathTo( + path, + fromPath, + fromAttr, + toPath, + toAttr) == false) + { + throw new ArgumentException("Paths must have a common prefix"); + } + + return path.ToString(); + } +#if true + return PathManager.IsSubfolder(toPath, fromPath) + ? "./" + OSTailoredCode.SimpleSubshell("realpath", $"--relative-to=\"{toPath}\" \"{fromPath}\"", $"invalid path {fromPath} or missing realpath binary") + : fromPath; +#else // written for Unix port but may be useful for .NET Core + // algorithm taken from https://stackoverflow.com/a/340454/7467292 + var dirSepChar = Path.DirectorySeparatorChar; + string from = !fromPath.EndsWith(dirSepChar.ToString()) + ? fromPath + dirSepChar + : fromPath; + string to = !toPath.EndsWith(dirSepChar.ToString()) + ? toPath + dirSepChar + : toPath; + + Uri fromUri = new Uri(from); + Uri toUri = new Uri(to); + + if (fromUri.Scheme != toUri.Scheme) + { + return toPath; } - return path.ToString(); + Uri relativeUri = fromUri.MakeRelativeUri(toUri); + string relativePath = Uri.UnescapeDataString(relativeUri.ToString()); + + if (string.Equals(toUri.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) + { + relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + + return relativePath.TrimEnd(dirSepChar); +#endif } + /// private static Win32.FileAttributes GetPathAttribute(string path) { var di = new DirectoryInfo(path.Split('|').First());