Skip to content

Commit

Permalink
Allowed the Gitiles URL for the HTTP remote to be different to the UR…
Browse files Browse the repository at this point in the history
…L for the web interface.
  • Loading branch information
reduckted committed Sep 22, 2024
1 parent 905141c commit c63627c
Show file tree
Hide file tree
Showing 31 changed files with 1,229 additions and 439 deletions.
16 changes: 12 additions & 4 deletions shared/handler-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,28 @@
"items": {
"type": "object",
"properties": {
"pattern": {
"remotePattern": {
"type": "string",
"description": "A regular expression to match on a remote URL. The captured groups are provided to the `http` and `ssh` templates."
},
"http": {
"$ref": "#/definitions/template",
"description": "The template to build the HTTP(S) URL of the remote server.\n\nCaptured groups from `pattern` are made available via the `match` variable."
"description": "The template to build the HTTP(S) remote URL.\n\nCaptured groups from `pattern` are made available via the `match` variable."
},
"ssh": {
"$ref": "#/definitions/template",
"description": "The template to build the SSH URL of the remote server.\n\nCaptured groups from `pattern` are made available via the `match` variable."
"description": "The template to build the SSH remote URL.\n\nCaptured groups from `pattern` are made available via the `match` variable."
},
"webPattern": {
"type": "string",
"description": "A regular expression to match on a web interface URL. The captured groups are provided to the `http` and `ssh` templates."
},
"web": {
"$ref": "#/definitions/template",
"description": "The template to build the web interface URL.\n\nCaptured groups from `pattern` are made available via the `match` variable."
}
},
"required": ["pattern", "http", "ssh"],
"required": ["remotePattern", "http", "ssh"],
"additionalProperties": false
}
},
Expand Down
7 changes: 4 additions & 3 deletions shared/handlers/azure-dev-ops-cloud.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
"name": "Azure Dev Ops Cloud",
"server": [
{
"pattern": "^https:\\/\\/(?:.+@)?dev\\.azure\\.com\\/([^\\/]+)\\/([^\\/]+)\\/_git\\/.+",
"remotePattern": "^https:\\/\\/(?:.+@)?dev\\.azure\\.com\\/([^\\/]+)\\/([^\\/]+)\\/_git\\/.+",
"http": "https://dev.azure.com/{{ match[1] }}/{{ match[2] }}/_git",
"ssh": "[email protected]:v3/{{ match[1] }}/{{ match[2] }}"
},
{
"pattern": "^(?:git@)?ssh\\.dev\\.azure\\.com:v3\\/([^\\/]+)\\/([^\\/]+)\\/.+$",
"remotePattern": "^(?:git@)?ssh\\.dev\\.azure\\.com:v3\\/([^\\/]+)\\/([^\\/]+)\\/.+$",
"http": "https://dev.azure.com/{{ match[1] }}/{{ match[2] }}/_git",
"ssh": "[email protected]:v3/{{ match[1] }}/{{ match[2] }}"
"ssh": "[email protected]:v3/{{ match[1] }}/{{ match[2] }}",
"webPattern": "^ONLY MATCH TO SSH REMOTE URLS$"
}
],
"branchRef": "abbreviated",
Expand Down
7 changes: 4 additions & 3 deletions shared/handlers/github.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
"name": "GitHub",
"server": [
{
"pattern": "^https:\\/\\/github.(?:com|dev)",
"remotePattern": "^https:\\/\\/github.(?:com|dev)",
"http": "https://github.com",
"ssh": "[email protected]"
},
{
"pattern": "^(?:git@)?github\\.com",
"remotePattern": "^(?:git@)?github\\.com",
"http": "https://github.com",
"ssh": "[email protected]"
"ssh": "[email protected]",
"webPattern": "^ONLY MATCH TO SSH REMOTE URLS$"
}
],
"branchRef": "abbreviated",
Expand Down
16 changes: 16 additions & 0 deletions shared/handlers/gitiles.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@
"remote": "https://git.company.com:1368/plugins/gitiles/foo/bar.git",
"result": "https://git.company.com:1368/plugins/gitiles/foo/bar/+/{{ commit }}/src/file.txt"
},
"misc": [
{
"name": "Web URL is different to clone URL",
"settings": {
"gitiles": [
{
"http": "https://git.company.com/a",
"ssh": "ssh://git.company.com:29418",
"web": "https://git.company.com/plugins/gitiles"
}
]
},
"remote": "https://git.company.com/a/foo/bar.git",
"result": "https://git.company.com/plugins/gitiles/foo/bar/+/master/src/file.txt"
}
],
"selection": {
"remote": "https://git.company.com:1368/plugins/gitiles/foo/bar.git",
"point": {
Expand Down
7 changes: 4 additions & 3 deletions shared/handlers/visual-studio-team-services.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
"name": "Visual Studio Team Services",
"server": [
{
"pattern": "^([^.]+)@vs-ssh\\.visualstudio\\.com:22(?:/(.+))?/_ssh/.+$",
"remotePattern": "^([^.]+)@vs-ssh\\.visualstudio\\.com:22(?:/(.+))?/_ssh/.+$",
"http": "https://{{ match[1] }}.visualstudio.com{% if match[2] %}/{{ match[2] }}{% endif %}/_git",
"ssh": "{{ match[1] }}@vs-ssh.visualstudio.com:22{% if match[2] %}/{{ match[2] }}{% endif %}/_ssh"
"ssh": "{{ match[1] }}@vs-ssh.visualstudio.com:22{% if match[2] %}/{{ match[2] }}{% endif %}/_ssh",
"webPattern": "^ONLY MATCH TO SSH REMOTE URLS$"
},
{
"pattern": "^https://([^.]+).visualstudio.com(?:/(.+))?/_git/.+$",
"remotePattern": "^https://([^.]+).visualstudio.com(?:/(.+))?/_git/.+$",
"http": "https://{{ match[1] }}.visualstudio.com{% if match[2] %}/{{ match[2] }}{% endif %}/_git",
"ssh": "{{ match[1] }}@vs-ssh.visualstudio.com:22{% if match[2] %}/{{ match[2] }}{% endif %}/_ssh"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@

<local:ServerDataGrid
ItemsSource="{Binding Servers}"
HasWebAddress="true"
HttpExample="https://git.mygitiles.com:8080/plugins/gitiles"
SshExample="ssh://git.mygitiles.com:29418"
WebExample="https://mygitiles.com/plugins/gitiles"
/>
</StackPanel>
</UserControl>
3 changes: 3 additions & 0 deletions visual-studio/source/GitWebLinks/Options/ServerListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ public class ServerListItem {

public string? Ssh { get; set; } = "";


public string? Web { get; set; } = "";

}
14 changes: 12 additions & 2 deletions visual-studio/source/GitWebLinks/Options/ServerOptionsPageBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ public abstract class ServerOptionsPageBase : OptionsPageBase {


internal IReadOnlyList<StaticServer> GetServers() {
return Servers.Select((x) => new StaticServer(x.Http ?? "", x.Ssh)).ToList();
return Servers.Select(
(x) => new StaticServer(
x.Http ?? "",
string.IsNullOrEmpty(x.Ssh) ? null : x.Ssh,
string.IsNullOrEmpty(x.Web) ? null : x.Web
)
).ToList();
}


Expand All @@ -38,7 +44,11 @@ public string JsonServers {

protected static string SerializeServers(IEnumerable<ServerListItem> servers) {
return JsonConvert.SerializeObject(
servers.Select((x) => new ServerListItem { Http = x.Http ?? "", Ssh = x.Ssh ?? "" })
servers.Select((x) => new ServerListItem {
Http = x.Http ?? "",
Ssh = x.Ssh,
Web = x.Web
})
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,20 @@ private class JsonHandlerDefinition {

private class JsonServer {

public string? Pattern { get; set; }
public string? RemotePattern { get; set; }


public string Http { get; set; } = "";


public string Ssh { get; set; } = "";


public string? WebPattern { get; set; }


public string? Web { get; set; }

}


Expand Down Expand Up @@ -89,6 +95,9 @@ private class JsonReverseServerSettings {

public string Ssh { get; set; } = "";


public string? Web { get; set; }

}


Expand Down
17 changes: 13 additions & 4 deletions visual-studio/source/GitWebLinks/Services/DefinitionProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,18 @@ private static IReadOnlyList<IServer> ParseServers(IReadOnlyList<JsonServer> jso
servers = new List<IServer>();

foreach (var server in json) {
if (server.Pattern is not null) {
servers.Add(new DynamicServer(new Regex(server.Pattern), Template.Parse(server.Http), Template.Parse(server.Ssh)));
if (server.RemotePattern is not null) {
servers.Add(
new DynamicServer(
new Regex(server.RemotePattern),
Template.Parse(server.Http),
Template.Parse(server.Ssh),
(server.WebPattern is not null) ? new Regex(server.WebPattern) : null,
(server.Web is not null) ? Template.Parse(server.Web) : null
)
);
} else {
servers.Add(new StaticServer(server.Http, server.Ssh));
servers.Add(new StaticServer(server.Http, server.Ssh, server.Web));
}
}

Expand All @@ -117,7 +125,8 @@ private static ReverseSettings ParseReverseSettings(JsonReverseSettings json) {
json.FileMayStartWithBranch,
new ReverseServerSettings(
Template.Parse(json.Server.Http),
Template.Parse(json.Server.Ssh)
Template.Parse(json.Server.Ssh),
(json.Server.Web is not null) ? Template.Parse(json.Server.Web) : null
),
new ReverseSelectionSettings(
Template.Parse(json.Selection.StartLine),
Expand Down
2 changes: 1 addition & 1 deletion visual-studio/source/GitWebLinks/Services/ILinkHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public interface ILinkHandler {
Task<UrlInfo?> GetUrlInfoAsync(string url, bool strict);


Task<bool> IsMatchAsync(string remoteUrl);
Task<bool> HandlesRemoteUrlAsync(string remoteUrl);

}
34 changes: 19 additions & 15 deletions visual-studio/source/GitWebLinks/Services/LinkHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ public LinkHandler(HandlerDefinition definition, ISettings settings, Git git) {
public string Name => _definition.Name;


public async Task<bool> IsMatchAsync(string remoteUrl) {
return await _server.MatchAsync(UrlHelpers.Normalize(remoteUrl)) is not null;
public async Task<bool> HandlesRemoteUrlAsync(string remoteUrl) {
return await _server.MatchRemoteUrlAsync(UrlHelpers.Normalize(remoteUrl)) is not null;
}


Expand All @@ -48,7 +48,7 @@ public async Task<CreateUrlResult> CreateUrlAsync(Repository repository, FileInf
throw new InvalidOperationException("The repository must have a remote.");
}

string remote;
string remoteUrl;
StaticServer address;
string refValue;
RefType refType;
Expand Down Expand Up @@ -86,15 +86,15 @@ public async Task<CreateUrlResult> CreateUrlAsync(Repository repository, FileInf

// Adjust the remote URL so that it's in a
// standard format that we can manipulate.
remote = UrlHelpers.Normalize(repository.Remote.Url);
remoteUrl = UrlHelpers.Normalize(repository.Remote.Url);

address = await GetAddressAsync(remote);
address = await GetAddressAsync(remoteUrl);
relativePath = GetRelativePath(repository.Root, file.FilePath);

data = TemplateData
.Create()
.Add("base", address.Http)
.Add("repository", GetRepositoryPath(remote, address))
.Add("base", address.Web ?? address.Http)
.Add("repository", GetRepositoryPath(remoteUrl, address))
.Add("ref", refValue)
.Add("commit", await GetRefAsync(LinkType.Commit, repository.Root, repository.Remote))
.Add("file", relativePath)
Expand Down Expand Up @@ -151,11 +151,11 @@ private static string ApplyModifications(string url, IReadOnlyList<QueryModifica
}


private async Task<StaticServer> GetAddressAsync(string remote) {
private async Task<StaticServer> GetAddressAsync(string remoteUrl) {
StaticServer? address;


address = await _server.MatchAsync(remote);
address = await _server.MatchRemoteUrlAsync(remoteUrl);

if (address is null) {
throw new InvalidOperationException("Could not find a matching address.");
Expand All @@ -168,11 +168,13 @@ private async Task<StaticServer> GetAddressAsync(string remote) {
private static StaticServer NormalizeServerUrls(StaticServer address) {
string http;
string? ssh;
string? web;

http = UrlHelpers.Normalize(address.Http);
ssh = address.Ssh is not null ? UrlHelpers.Normalize(address.Ssh) : null;
web = address.Web is not null ? UrlHelpers.Normalize(address.Web) : null;

return new StaticServer(http, ssh);
return new StaticServer(http, ssh, web);
}


Expand Down Expand Up @@ -298,7 +300,7 @@ private string GetRelativePath(string from, string to) {

// If the file is a symbolic link, or is under a directory that's a
// symbolic link, then we want to resolve the path to the real file
// because the sybmolic link won't be in the Git repository.
// because the symbolic link won't be in the Git repository.
if (IsSymbolicLink(to, from)) {
try {
to = GetRealPath(to);
Expand Down Expand Up @@ -449,13 +451,13 @@ private static bool TryGetFinalPathNameByHandle(IntPtr handle, int bufferSize, o
}


public async Task<UrlInfo?> GetUrlInfoAsync(string url, bool strict) {
public async Task<UrlInfo?> GetUrlInfoAsync(string webUrl, bool strict) {
StaticServer? address;
Match match;


// See if the URL matches the server address for the handler.
address = await _server.MatchAsync(url);
address = await _server.MatchWebUrlAsync(webUrl);

// If we are performing a strict match, then the
// URL must match to this handler's server.
Expand All @@ -467,7 +469,7 @@ private static bool TryGetFinalPathNameByHandle(IntPtr handle, int bufferSize, o
address = NormalizeServerUrls(address);
}

match = _definition.Reverse.Pattern.Match(url);
match = _definition.Reverse.Pattern.Match(webUrl);

if (match.Success) {
Hash hash;
Expand All @@ -480,14 +482,16 @@ private static bool TryGetFinalPathNameByHandle(IntPtr handle, int bufferSize, o
.Create()
.Add("http", address?.Http)
.Add("ssh", address?.Ssh)
.Add("web", address?.Web)
.Add(match)
.ToHash();

file = _definition.Reverse.File.Render(hash);

server = new StaticServer(
_definition.Reverse.Server.Http.Render(hash),
_definition.Reverse.Server.Ssh.Render(hash)
_definition.Reverse.Server.Ssh.Render(hash),
_definition.Reverse.Server.Web?.Render(hash)
);

selection = new PartialSelectedRange(
Expand Down
14 changes: 7 additions & 7 deletions visual-studio/source/GitWebLinks/Services/LinkHandlerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public LinkHandlerProvider(ISettings settings, Git git, ILogger logger) {
foreach (ILinkHandler handler in _handlers) {
await _logger.LogAsync($"Testing '{handler.Name}");

if (await handler.IsMatchAsync(repository.Remote.Url)) {
if (await handler.HandlesRemoteUrlAsync(repository.Remote.Url)) {
await _logger.LogAsync($"Handler '{handler.Name}' is a match.");
return handler;
}
Expand All @@ -44,23 +44,23 @@ public LinkHandlerProvider(ISettings settings, Git git, ILogger logger) {
}


public async Task<IReadOnlyCollection<UrlInfo>> GetUrlInfoAsync(string url) {
public async Task<IReadOnlyCollection<UrlInfo>> GetUrlInfoAsync(string webUrl) {
IReadOnlyCollection<UrlInfo> output;


await _logger.LogAsync($"Finding file info for URL '{url}'.");
output = await InternalGetUrlInfoAsync(url, true);
await _logger.LogAsync($"Finding file info for URL '{webUrl}'.");
output = await InternalGetUrlInfoAsync(webUrl, true);

if (output.Count == 0) {
await _logger.LogAsync("No strict matches found. Trying again with loose matching.");
output = await InternalGetUrlInfoAsync(url, false);
output = await InternalGetUrlInfoAsync(webUrl, false);
}

return output;
}


private async Task<IReadOnlyCollection<UrlInfo>> InternalGetUrlInfoAsync(string url, bool strict) {
private async Task<IReadOnlyCollection<UrlInfo>> InternalGetUrlInfoAsync(string webUrl, bool strict) {
List<UrlInfo> output;


Expand All @@ -70,7 +70,7 @@ private async Task<IReadOnlyCollection<UrlInfo>> InternalGetUrlInfoAsync(string
UrlInfo? info;


info = await handler.GetUrlInfoAsync(url, strict);
info = await handler.GetUrlInfoAsync(webUrl, strict);

if (info is not null) {
await _logger.LogAsync($"The handler '{handler.Name}' mapped the file to '{info}'.");
Expand Down
Loading

0 comments on commit c63627c

Please sign in to comment.