private static void AssertSeparatorChoice(string path, char?separator) { if (separator == null) { return; } var root = GetPathRoot(path); if (root == null) { return; } ControlFlow.Assert(!IsWinRoot(root) || separator == WinSeparator, $"For Windows-rooted paths the separator must be '{WinSeparator}'."); ControlFlow.Assert(!IsUncRoot(root) || separator == UncSeparator, $"For UNC-rooted paths the separator must be '{UncSeparator}'."); ControlFlow.Assert(!IsUnixRoot(root) || separator == UnixSeparator, $"For Unix-rooted paths the separator must be '{UnixSeparator}'."); }
// TODO: check usages public static string GetRelativePath(string basePath, string destinationPath, bool normalize = true) { basePath = NormalizePath(basePath); destinationPath = NormalizePath(destinationPath); var separator = GetSeparator(basePath); ControlFlow.Assert(separator == GetSeparator(destinationPath), "Separators do not match."); ControlFlow.Assert(!IsWinRoot(basePath) || Path.GetPathRoot(basePath) == Path.GetPathRoot(destinationPath), "Root must be same."); var baseParts = basePath.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries); var destinationParts = destinationPath.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries); var sameParts = baseParts.Zip(destinationParts, (a, b) => new { Base = a, Destination = b }) .Count(x => x.Base.Equals(x.Destination, StringComparison.OrdinalIgnoreCase)); return(Enumerable.Repeat("..", baseParts.Length - sameParts).ToList() .Concat(destinationParts.Skip(sameParts).ToList()).Join(separator)); }
// ReSharper disable once CyclomaticComplexity public static string NormalizePath(string path, char?separator = null) { AssertSeparatorChoice(path, separator); path = path ?? string.Empty; separator = separator ?? GetSeparator(path); var root = GetPathRoot(path); var tail = root == null ? path : path.Substring(root.Length); var tailParts = tail.Split(s_allSeparators, StringSplitOptions.RemoveEmptyEntries).ToList(); for (var i = 0; i < tailParts.Count;) { var part = tailParts[i]; if (IsUpwardsDirectory(part)) { if (tailParts.Take(i).All(IsUpwardsDirectory)) { ControlFlow.Assert(i > 0 || root == null, $"Cannot normalize '{path}' beyond path root."); i++; continue; } tailParts.RemoveAt(i); tailParts.RemoveAt(i - 1); i--; continue; } if (IsSameDirectory(part)) { tailParts.RemoveAt(i); continue; } i++; } return(Combine(root, tailParts.Join(separator.ToString()), separator)); }