Skip to content

Commit 0880f76

Browse files
authored
Improvements to canonical URI API (microsoft#182667)
* Improve API names * Allow requesting a specific scheme * Implement ile uri support
1 parent c2b15fe commit 0880f76

20 files changed

+241
-202
lines changed

extensions/git/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"diffCommand",
1414
"contribEditorContentMenu",
1515
"contribEditSessions",
16-
"canonicalUriIdentityProvider",
16+
"canonicalUriProvider",
1717
"contribViewsWelcome",
1818
"editSessionIdentityProvider",
1919
"quickDiffProvider",

extensions/git/src/editSessionIdentityProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class GitEditSessionIdentityProvider implements vscode.EditSessionIdentit
3535
}
3636

3737
const remoteUrl = repository.remotes.find((remote) => remote.name === repository.HEAD?.upstream?.remote)?.pushUrl?.replace(/^(git@[^\/:]+)(:)/i, 'ssh://$1/');
38-
const remote = remoteUrl ? await vscode.workspace.provideCanonicalUriIdentity(vscode.Uri.parse(remoteUrl), token) : null;
38+
const remote = remoteUrl ? await vscode.workspace.getCanonicalUri(vscode.Uri.parse(remoteUrl), { targetScheme: 'https' }, token) : null;
3939

4040
return JSON.stringify({
4141
remote: remote?.toString() ?? remoteUrl,

extensions/git/src/typings/vscode.proposed.canonicalUriIdentityProvider.d.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
declare module 'vscode' {
7+
8+
// https://github.com/microsoft/vscode/issues/180582
9+
10+
export namespace workspace {
11+
/**
12+
*
13+
* @param scheme The URI scheme that this provider can provide canonical URIs for.
14+
* A canonical URI represents the conversion of a resource's alias into a source of truth URI.
15+
* Multiple aliases may convert to the same source of truth URI.
16+
* @param provider A provider which can convert URIs of scheme @param scheme to
17+
* a canonical URI which is stable across machines.
18+
*/
19+
export function registerCanonicalUriProvider(scheme: string, provider: CanonicalUriProvider): Disposable;
20+
21+
/**
22+
*
23+
* @param uri The URI to provide a canonical URI for.
24+
* @param token A cancellation token for the request.
25+
*/
26+
export function getCanonicalUri(uri: Uri, options: CanonicalUriRequestOptions, token: CancellationToken): ProviderResult<Uri>;
27+
}
28+
29+
export interface CanonicalUriProvider {
30+
/**
31+
*
32+
* @param uri The URI to provide a canonical URI for.
33+
* @param options Options that the provider should honor in the URI it returns.
34+
* @param token A cancellation token for the request.
35+
* @returns The canonical URI for the requested URI or undefined if no canonical URI can be provided.
36+
*/
37+
provideCanonicalUri(uri: Uri, options: CanonicalUriRequestOptions, token: CancellationToken): ProviderResult<Uri>;
38+
}
39+
40+
export interface CanonicalUriRequestOptions {
41+
/**
42+
*
43+
* The desired scheme of the canonical URI.
44+
*/
45+
targetScheme: string;
46+
}
47+
}

extensions/github/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"enabledApiProposals": [
2929
"contribShareMenu",
3030
"contribEditSessions",
31-
"canonicalUriIdentityProvider"
31+
"canonicalUriProvider"
3232
],
3333
"contributes": {
3434
"commands": [

extensions/github/src/canonicalUriIdentityProvider.ts

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { CancellationToken, CanonicalUriProvider, CanonicalUriRequestOptions, Disposable, ProviderResult, Uri, workspace } from 'vscode';
7+
import { API } from './typings/git';
8+
9+
const SUPPORTED_SCHEMES = ['ssh', 'https', 'file'];
10+
11+
export class GitHubCanonicalUriProvider implements CanonicalUriProvider {
12+
13+
private disposables: Disposable[] = [];
14+
constructor(private gitApi: API) {
15+
this.disposables.push(...SUPPORTED_SCHEMES.map((scheme) => workspace.registerCanonicalUriProvider(scheme, this)));
16+
}
17+
18+
dispose() { this.disposables.forEach((disposable) => disposable.dispose()); }
19+
20+
provideCanonicalUri(uri: Uri, options: CanonicalUriRequestOptions, _token: CancellationToken): ProviderResult<Uri> {
21+
if (options.targetScheme !== 'https') {
22+
return;
23+
}
24+
25+
switch (uri.scheme) {
26+
case 'file': {
27+
const repository = this.gitApi.getRepository(uri);
28+
const remote = repository?.state.remotes.find((remote) => remote.name === repository.state.HEAD?.remote)?.pushUrl?.replace(/^(git@[^\/:]+)(:)/i, 'ssh://$1/');
29+
if (remote) {
30+
return toHttpsGitHubRemote(uri);
31+
}
32+
}
33+
default:
34+
return toHttpsGitHubRemote(uri);
35+
}
36+
}
37+
}
38+
39+
function toHttpsGitHubRemote(uri: Uri) {
40+
if (uri.scheme === 'ssh' && uri.authority === '[email protected]') {
41+
// if this is a git@github.com URI, return the HTTPS equivalent
42+
const [owner, repo] = (uri.path.endsWith('.git') ? uri.path.slice(0, -4) : uri.path).split('/').filter((segment) => segment.length > 0);
43+
return Uri.parse(`https://github.com/${owner}/${repo}`);
44+
}
45+
if (uri.scheme === 'https' && uri.authority === 'github.com') {
46+
return uri;
47+
}
48+
return undefined;
49+
}

extensions/github/src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { GithubPushErrorHandler } from './pushErrorHandler';
1313
import { GitBaseExtension } from './typings/git-base';
1414
import { GithubRemoteSourcePublisher } from './remoteSourcePublisher';
1515
import { GithubBranchProtectionProviderManager } from './branchProtection';
16-
import { GitHubCanonicalUriIdentityProvider } from './canonicalUriIdentityProvider';
16+
import { GitHubCanonicalUriProvider } from './canonicalUriProvider';
1717

1818
export function activate(context: ExtensionContext): void {
1919
const disposables: Disposable[] = [];
@@ -30,7 +30,6 @@ export function activate(context: ExtensionContext): void {
3030

3131
disposables.push(initializeGitBaseExtension());
3232
disposables.push(initializeGitExtension(context, logger));
33-
disposables.push(new GitHubCanonicalUriIdentityProvider());
3433
}
3534

3635
function initializeGitBaseExtension(): Disposable {
@@ -95,6 +94,7 @@ function initializeGitExtension(context: ExtensionContext, logger: LogOutputChan
9594
disposables.add(new GithubBranchProtectionProviderManager(gitAPI, context.globalState, logger));
9695
disposables.add(gitAPI.registerPushErrorHandler(new GithubPushErrorHandler()));
9796
disposables.add(gitAPI.registerRemoteSourcePublisher(new GithubRemoteSourcePublisher(gitAPI)));
97+
disposables.add(new GitHubCanonicalUriProvider(gitAPI));
9898
setGitHubContext(gitAPI, disposables);
9999

100100
commands.executeCommand('setContext', 'git-base.gitEnabled', true);

extensions/github/src/typings/vscode.proposed.canonicalUriIdentityProvider.d.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
declare module 'vscode' {
7+
8+
// https://github.com/microsoft/vscode/issues/180582
9+
10+
export namespace workspace {
11+
/**
12+
*
13+
* @param scheme The URI scheme that this provider can provide canonical URIs for.
14+
* A canonical URI represents the conversion of a resource's alias into a source of truth URI.
15+
* Multiple aliases may convert to the same source of truth URI.
16+
* @param provider A provider which can convert URIs of scheme @param scheme to
17+
* a canonical URI which is stable across machines.
18+
*/
19+
export function registerCanonicalUriProvider(scheme: string, provider: CanonicalUriProvider): Disposable;
20+
21+
/**
22+
*
23+
* @param uri The URI to provide a canonical URI for.
24+
* @param token A cancellation token for the request.
25+
*/
26+
export function getCanonicalUri(uri: Uri, options: CanonicalUriRequestOptions, token: CancellationToken): ProviderResult<Uri>;
27+
}
28+
29+
export interface CanonicalUriProvider {
30+
/**
31+
*
32+
* @param uri The URI to provide a canonical URI for.
33+
* @param options Options that the provider should honor in the URI it returns.
34+
* @param token A cancellation token for the request.
35+
* @returns The canonical URI for the requested URI or undefined if no canonical URI can be provided.
36+
*/
37+
provideCanonicalUri(uri: Uri, options: CanonicalUriRequestOptions, token: CancellationToken): ProviderResult<Uri>;
38+
}
39+
40+
export interface CanonicalUriRequestOptions {
41+
/**
42+
*
43+
* The desired scheme of the canonical URI.
44+
*/
45+
targetScheme: string;
46+
}
47+
}

0 commit comments

Comments
 (0)