Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/git/src/protocolHandler.ts
5239 views
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 { UriHandler, Uri, window, Disposable, commands, LogOutputChannel, l10n } from 'vscode';
7
import { dispose, isWindows } from './util';
8
import * as querystring from 'querystring';
9
10
const schemes = isWindows ?
11
new Set(['git', 'http', 'https', 'ssh']) :
12
new Set(['file', 'git', 'http', 'https', 'ssh']);
13
14
const refRegEx = /^$|[~\^:\\\*\s\[\]]|^-|^\.|\/\.|\.\.|\.lock\/|\.lock$|\/$|\.$/;
15
16
export class GitProtocolHandler implements UriHandler {
17
18
private disposables: Disposable[] = [];
19
20
constructor(private readonly logger: LogOutputChannel) {
21
this.disposables.push(window.registerUriHandler(this));
22
}
23
24
// example code-oss://vscode.git/clone?url=https://github.com/microsoft/vscode
25
handleUri(uri: Uri): void {
26
this.logger.info(`[GitProtocolHandler][handleUri] URI:(${uri.toString()})`);
27
28
switch (uri.path) {
29
case '/clone': this.clone(uri);
30
}
31
}
32
33
private async clone(uri: Uri): Promise<void> {
34
const data = querystring.parse(uri.query);
35
const ref = data.ref;
36
37
if (!data.url) {
38
this.logger.warn('[GitProtocolHandler][clone] Failed to open URI:' + uri.toString());
39
return;
40
}
41
42
if (Array.isArray(data.url) && data.url.length === 0) {
43
this.logger.warn('[GitProtocolHandler][clone] Failed to open URI:' + uri.toString());
44
return;
45
}
46
47
if (ref !== undefined && typeof ref !== 'string') {
48
this.logger.warn('[GitProtocolHandler][clone] Failed to open URI due to multiple references:' + uri.toString());
49
return;
50
}
51
52
let cloneUri: Uri;
53
try {
54
let rawUri = Array.isArray(data.url) ? data.url[0] : data.url;
55
56
// Handle SSH Uri
57
// Ex: [email protected]:microsoft/vscode.git
58
rawUri = rawUri.replace(/^(git@[^\/:]+)(:)/i, 'ssh://$1/');
59
60
cloneUri = Uri.parse(rawUri, true);
61
62
// Validate against supported schemes
63
if (!schemes.has(cloneUri.scheme.toLowerCase())) {
64
throw new Error('Unsupported scheme.');
65
}
66
67
// Validate the reference
68
if (typeof ref === 'string' && refRegEx.test(ref)) {
69
throw new Error('Invalid reference.');
70
}
71
}
72
catch (ex) {
73
this.logger.warn('[GitProtocolHandler][clone] Invalid URI:' + uri.toString());
74
return;
75
}
76
77
if (!(await commands.getCommands(true)).includes('git.clone')) {
78
this.logger.error('[GitProtocolHandler][clone] Could not complete git clone operation as git installation was not found.');
79
80
const errorMessage = l10n.t('Could not clone your repository as Git is not installed.');
81
const downloadGit = l10n.t('Download Git');
82
83
if (await window.showErrorMessage(errorMessage, { modal: true }, downloadGit) === downloadGit) {
84
commands.executeCommand('vscode.open', Uri.parse('https://aka.ms/vscode-download-git'));
85
}
86
87
return;
88
} else {
89
const cloneTarget = cloneUri.toString(true);
90
this.logger.info(`[GitProtocolHandler][clone] Executing git.clone for ${cloneTarget}`);
91
commands.executeCommand('git.clone', cloneTarget, undefined, { ref: ref });
92
}
93
}
94
95
dispose(): void {
96
this.disposables = dispose(this.disposables);
97
}
98
}
99
100