From 949b17b54b03367721b4f07d1d32e8a9bd752c79 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Mon, 1 Feb 2021 12:29:18 -0800 Subject: [PATCH] Allow retrieval of the "relative file path" from the source link map It can be helpful for consumers of the Source Link to know what portion of the file path provided to the query is substituted into the URL. One example is for building a heuristic file path on disk to store the downloaded source link file to. This relative path can give end users more context on where the file is located in the original repository. This change add a new TryGetUri overload that provides the "relative file path" as another out param. It also updates the tests to add coverage for this. --- .../SourceLinkMapTests.cs | 12 +++++++++ src/SourceLink.Tools/SourceLinkMap.cs | 25 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/SourceLink.Tools.UnitTests/SourceLinkMapTests.cs b/src/SourceLink.Tools.UnitTests/SourceLinkMapTests.cs index db134dfa..98c64a0b 100644 --- a/src/SourceLink.Tools.UnitTests/SourceLinkMapTests.cs +++ b/src/SourceLink.Tools.UnitTests/SourceLinkMapTests.cs @@ -66,12 +66,24 @@ public void Entries() Assert.True(map.TryGetUri(@"C:\a", out var url)); Assert.Equal("http://server/[]", url); + Assert.True(map.TryGetUri(@"C:\a", out url, out var relativeFilePath)); + Assert.Equal("http://server/[]", url); + Assert.Equal("", relativeFilePath); + Assert.True(map.TryGetUri(@"C:\a\b\c\d\e", out url)); Assert.Equal("http://server/[/b/c/d/e]", url); + Assert.True(map.TryGetUri(@"C:\a\b\c\d\e", out url, out relativeFilePath)); + Assert.Equal("http://server/[/b/c/d/e]", url); + Assert.Equal(@"/b/c/d/e", relativeFilePath); + Assert.True(map.TryGetUri(@"C:\b", out url)); Assert.Equal("http://b", url); + Assert.True(map.TryGetUri(@"C:\b", out url, out relativeFilePath)); + Assert.Equal("http://b", url); + Assert.Equal("b", relativeFilePath); + Assert.False(map.TryGetUri(@"C:\b\c", out _)); } diff --git a/src/SourceLink.Tools/SourceLinkMap.cs b/src/SourceLink.Tools/SourceLinkMap.cs index 2aff6b81..0f28b492 100644 --- a/src/SourceLink.Tools/SourceLinkMap.cs +++ b/src/SourceLink.Tools/SourceLinkMap.cs @@ -189,6 +189,24 @@ private static bool TryParseEntry(string key, string value, out Entry entry) [NotNullWhen(true)] #endif out string? uri) + { + return TryGetUri(path, out uri, out _); + } + + /// + /// Maps specified to the corresponding URL. + /// + /// is null. + public bool TryGetUri( + string path, +#if NETCOREAPP + [NotNullWhen(true)] +#endif + out string? uri, +#if NETCOREAPP + [NotNullWhen(true)] +#endif + out string? relativeFilePath) { if (path == null) { @@ -198,6 +216,7 @@ private static bool TryParseEntry(string key, string value, out Entry entry) if (path.IndexOf('*') >= 0) { uri = null; + relativeFilePath = null; return false; } @@ -209,20 +228,24 @@ private static bool TryParseEntry(string key, string value, out Entry entry) { if (path.StartsWith(file.Path, StringComparison.OrdinalIgnoreCase)) { - var escapedPath = string.Join("/", path.Substring(file.Path.Length).Split(new[] { '/', '\\' }).Select(Uri.EscapeDataString)); + var relativePath = path.Substring(file.Path.Length).Replace('\\', '/'); + var escapedPath = string.Join("/", relativePath.Split('/').Select(Uri.EscapeDataString)); uri = mappedUri.Prefix + escapedPath + mappedUri.Suffix; + relativeFilePath = relativePath; return true; } } else if (string.Equals(path, file.Path, StringComparison.OrdinalIgnoreCase)) { Debug.Assert(mappedUri.Suffix.Length == 0); + relativeFilePath = Path.GetFileName(file.Path); uri = mappedUri.Prefix; return true; } } uri = null; + relativeFilePath = null; return false; } }