diff --git a/docs/reference/docfx-environment-variables-reference.md b/docs/reference/docfx-environment-variables-reference.md index 80b8e357822..e48301347d1 100644 --- a/docs/reference/docfx-environment-variables-reference.md +++ b/docs/reference/docfx-environment-variables-reference.md @@ -14,10 +14,10 @@ If set true. Keep following debug info in output HTML. Used to override git branch name. -## `DOCFX_SOURCE_REPOSITORY` +## `DOCFX_SOURCE_REPOSITORY_URL` Used to override git organization and repository names. -It must be defined in the `{organization}/{repository_name}` format (e.g.`dotnet/docfx`). +It must be defined in the `https://{host_name}/{organization}/{repository_name}` format (e.g.`https://github.com/dotnet/docfx`). ## `DOCFX_NO_CHECK_CERTIFICATE_REVOCATION_LIST` diff --git a/src/Docfx.Common/Git/GitUtility.cs b/src/Docfx.Common/Git/GitUtility.cs index ec42755b988..cc8016ae1e0 100644 --- a/src/Docfx.Common/Git/GitUtility.cs +++ b/src/Docfx.Common/Git/GitUtility.cs @@ -184,48 +184,42 @@ static string GitUrlToHttps(string url) } /// - /// Rewrite path if `DOCFX_SOURCE_REPOSITORY` environment variable is specified. + /// Rewrite path if `DOCFX_SOURCE_REPOSITORY_URL` environment variable is specified. /// private static string ResolveDocfxSourceRepoUrl(string originalUrl) { - var docfxSourceRepoUrl = Environment.GetEnvironmentVariable("DOCFX_SOURCE_REPOSITORY"); + var docfxSourceRepoUrl = Environment.GetEnvironmentVariable("DOCFX_SOURCE_REPOSITORY_URL"); if (docfxSourceRepoUrl == null) return originalUrl; + if (!Uri.TryCreate(originalUrl, UriKind.Absolute, out var parsedOriginalUrl) + || !Uri.TryCreate(docfxSourceRepoUrl, UriKind.Absolute, out var parsedOverrideUrl) + || parsedOriginalUrl.Host != parsedOverrideUrl.Host) + { + return originalUrl; + } + // Parse value that defined with `{orgName}/{repoName}` format. - var parts = docfxSourceRepoUrl.Split('/', StringSplitOptions.TrimEntries); - if (parts.Length != 2) + var parts = parsedOverrideUrl.LocalPath.Split('/', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + if (parts.Length < 2) return originalUrl; string orgName = parts[0]; string repoName = parts[1]; - if (!Uri.TryCreate(originalUrl, UriKind.Absolute, out var parsedUrl)) - { - return originalUrl; - } - - switch (parsedUrl.Host) + switch (parsedOriginalUrl.Host) { case "github.com": case "bitbucket.org": case "dev.azure.com": { // Replace `/{orgName}/{repoName}` and remove `.git` suffix. - var builder = new UriBuilder(parsedUrl); - builder.Path = Regex.Replace(builder.Path, @"^/[^/]+/[^/]+", $"/{orgName}/{repoName}") - .TrimEnd(".git"); + var builder = new UriBuilder(parsedOriginalUrl); + builder.Path = Regex.Replace(builder.Path.TrimEnd(".git"), @"^/[^/]+/[^/]+", $"/{orgName}/{repoName}"); return builder.Uri.ToString(); } - case string hostName when hostName.EndsWith(".visualstudio.com"): - { - // Replace `https://{orgName}.visualstudio.com/{repoName}`. - var builder = new UriBuilder(parsedUrl); - builder.Host = $"{orgName}.visualstudio.com"; - builder.Path = Regex.Replace(builder.Path, @"^/[^/]+", $"/{repoName}"); - return builder.Uri.ToString(); - } + // Currently other URL formats are not supported (e.g. visualstudio.com, GitHub Enterprise Server) default: return originalUrl; } diff --git a/test/Docfx.Common.Tests/GitUtilityWithSourceRepoUrlTest.cs b/test/Docfx.Common.Tests/GitUtilityWithSourceRepoUrlTest.cs index e805c48a8ff..1b949ae9a1d 100644 --- a/test/Docfx.Common.Tests/GitUtilityWithSourceRepoUrlTest.cs +++ b/test/Docfx.Common.Tests/GitUtilityWithSourceRepoUrlTest.cs @@ -7,7 +7,7 @@ namespace Docfx.Common.Tests; [Collection("docfx STA")] -public class GitUtilityWithSourceRepoUrlTest : IDisposable +public class GitUtilityWithSourceRepositoryUrlTest : IDisposable { private readonly string _originalBranchName; private readonly string _originalSourceRepoUrl; @@ -17,21 +17,21 @@ public class GitUtilityWithSourceRepoUrlTest : IDisposable private const string BRANCH_NAME = "special-branch"; private const string DOCFX_SOURCE_BRANCH_NAME = nameof(DOCFX_SOURCE_BRANCH_NAME); - private const string DOCFX_SOURCE_REPOSITORY = nameof(DOCFX_SOURCE_REPOSITORY); + private const string DOCFX_SOURCE_REPOSITORY_URL = nameof(DOCFX_SOURCE_REPOSITORY_URL); - public GitUtilityWithSourceRepoUrlTest() + public GitUtilityWithSourceRepositoryUrlTest() { _originalBranchName = Environment.GetEnvironmentVariable(DOCFX_SOURCE_BRANCH_NAME); - _originalSourceRepoUrl = Environment.GetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY); + _originalSourceRepoUrl = Environment.GetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY_URL); Environment.SetEnvironmentVariable(DOCFX_SOURCE_BRANCH_NAME, BRANCH_NAME); - Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY, $"{ORG_NAME}/{REPO_NAME}"); + Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY_URL, $"https://github.com/{ORG_NAME}/{REPO_NAME}"); } public void Dispose() { Environment.SetEnvironmentVariable(DOCFX_SOURCE_BRANCH_NAME, _originalBranchName); - Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY, _originalSourceRepoUrl); + Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY_URL, _originalSourceRepoUrl); } [Fact] @@ -56,15 +56,8 @@ public void RawContentUrlToContentUrlTest() [Theory] [InlineData("https://github.com/user/repo.git", "main", "path/to/file.cs", 0, $"https://github.com/{ORG_NAME}/{REPO_NAME}/blob/main/path/to/file.cs")] [InlineData("https://github.com/user/repo.git", "main", "path/to/file.cs", 10, $"https://github.com/{ORG_NAME}/{REPO_NAME}/blob/main/path/to/file.cs#L10")] - [InlineData("https://bitbucket.org/user/repo.git", "main", "path/to/file.cs", 0, $"https://bitbucket.org/{ORG_NAME}/{REPO_NAME}/src/main/path/to/file.cs")] - [InlineData("https://bitbucket.org/user/repo.git", "main", "path/to/file.cs", 10, $"https://bitbucket.org/{ORG_NAME}/{REPO_NAME}/src/main/path/to/file.cs#lines-10")] - [InlineData("https://dev.azure.com/user/repo/_git/repo", "main", "path/to/file.cs", 0, $"https://dev.azure.com/{ORG_NAME}/{REPO_NAME}/_git/repo?path=path/to/file.cs&version=GBmain")] - [InlineData("https://dev.azure.com/user/repo/_git/repo", "0123456789abcdef0123456789abcdef01234567", "path/to/file.cs", 10, $"https://dev.azure.com/{ORG_NAME}/{REPO_NAME}/_git/repo?path=path/to/file.cs&version=GC0123456789abcdef0123456789abcdef01234567&line=10")] - [InlineData("https://user.visualstudio.com/repo/_git/repo", "main", "path/to/file.cs", 0, $"https://{ORG_NAME}.visualstudio.com/{REPO_NAME}/_git/repo?path=path/to/file.cs&version=GBmain")] - [InlineData("https://user.visualstudio.com/repo/_git/repo", "0123456789abcdef0123456789abcdef01234567", "path/to/file.cs", 10, $"https://{ORG_NAME}.visualstudio.com/{REPO_NAME}/_git/repo?path=path/to/file.cs&version=GC0123456789abcdef0123456789abcdef01234567&line=10")] [InlineData("git@github.com:user/repo.git", "main", "path/to/file.cs", 0, $"https://github.com/{ORG_NAME}/{REPO_NAME}/blob/main/path/to/file.cs")] - [InlineData("ssh://mseng@vs-ssh.visualstudio.com:22/FakeProject/_ssh/Docfx", "main", "path/to/file.cs", 0, $"https://{ORG_NAME}.visualstudio.com/{REPO_NAME}/_ssh/Docfx?path=path/to/file.cs&version=GBmain")] - public void GetSourceUrlTest(string repo, string branch, string path, int line, string result) + public void GetSourceUrlTest_GitHub(string repo, string branch, string path, int line, string result) { Assert.Equal(result, GitUtility.GetSourceUrl(new(repo, branch, path, line))); } diff --git a/test/docfx.Snapshot.Tests/SamplesTest.cs b/test/docfx.Snapshot.Tests/SamplesTest.cs index 962d87e8755..8586d0800ab 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.cs +++ b/test/docfx.Snapshot.Tests/SamplesTest.cs @@ -22,16 +22,16 @@ public class SamplesTest : IDisposable { private static readonly string s_samplesDir = Path.GetFullPath("../../../../../samples"); - private const string DOCFX_SOURCE_REPOSITORY = nameof(DOCFX_SOURCE_REPOSITORY); + private const string DOCFX_SOURCE_REPOSITORY_URL = nameof(DOCFX_SOURCE_REPOSITORY_URL); public SamplesTest() { - Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY, "dotnet/docfx"); + Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY_URL, "https://github.com/dotnet/docfx"); } public void Dispose() { - Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY, null); + Environment.SetEnvironmentVariable(DOCFX_SOURCE_REPOSITORY_URL, null); } private class SamplesFactAttribute : FactAttribute