Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/git/src/editSessionIdentityProvider.ts
3316 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 * as path from 'path';
7
import * as vscode from 'vscode';
8
import { RefType } from './api/git';
9
import { Model } from './model';
10
11
export class GitEditSessionIdentityProvider implements vscode.EditSessionIdentityProvider, vscode.Disposable {
12
13
private providerRegistration: vscode.Disposable;
14
15
constructor(private model: Model) {
16
this.providerRegistration = vscode.Disposable.from(
17
vscode.workspace.registerEditSessionIdentityProvider('file', this),
18
vscode.workspace.onWillCreateEditSessionIdentity((e) => {
19
e.waitUntil(
20
this._onWillCreateEditSessionIdentity(e.workspaceFolder).catch(err => {
21
if (err instanceof vscode.CancellationError) {
22
throw err;
23
}
24
})
25
);
26
})
27
);
28
}
29
30
dispose() {
31
this.providerRegistration.dispose();
32
}
33
34
async provideEditSessionIdentity(workspaceFolder: vscode.WorkspaceFolder, token: vscode.CancellationToken): Promise<string | undefined> {
35
await this.model.openRepository(path.dirname(workspaceFolder.uri.fsPath));
36
37
const repository = this.model.getRepository(workspaceFolder.uri);
38
await repository?.status();
39
40
if (!repository || !repository?.HEAD?.upstream) {
41
return undefined;
42
}
43
44
const remoteUrl = repository.remotes.find((remote) => remote.name === repository.HEAD?.upstream?.remote)?.pushUrl?.replace(/^(git@[^\/:]+)(:)/i, 'ssh://$1/');
45
const remote = remoteUrl ? await vscode.workspace.getCanonicalUri(vscode.Uri.parse(remoteUrl), { targetScheme: 'https' }, token) : null;
46
47
return JSON.stringify({
48
remote: remote?.toString() ?? remoteUrl,
49
ref: repository.HEAD?.upstream?.name ?? null,
50
sha: repository.HEAD?.commit ?? null,
51
});
52
}
53
54
provideEditSessionIdentityMatch(identity1: string, identity2: string): vscode.EditSessionIdentityMatch {
55
try {
56
const normalizedIdentity1 = normalizeEditSessionIdentity(identity1);
57
const normalizedIdentity2 = normalizeEditSessionIdentity(identity2);
58
59
if (normalizedIdentity1.remote === normalizedIdentity2.remote &&
60
normalizedIdentity1.ref === normalizedIdentity2.ref &&
61
normalizedIdentity1.sha === normalizedIdentity2.sha) {
62
// This is a perfect match
63
return vscode.EditSessionIdentityMatch.Complete;
64
} else if (normalizedIdentity1.remote === normalizedIdentity2.remote &&
65
normalizedIdentity1.ref === normalizedIdentity2.ref &&
66
normalizedIdentity1.sha !== normalizedIdentity2.sha) {
67
// Same branch and remote but different SHA
68
return vscode.EditSessionIdentityMatch.Partial;
69
} else {
70
return vscode.EditSessionIdentityMatch.None;
71
}
72
} catch (ex) {
73
return vscode.EditSessionIdentityMatch.Partial;
74
}
75
}
76
77
private async _onWillCreateEditSessionIdentity(workspaceFolder: vscode.WorkspaceFolder): Promise<void> {
78
await this._doPublish(workspaceFolder);
79
}
80
81
private async _doPublish(workspaceFolder: vscode.WorkspaceFolder) {
82
await this.model.openRepository(path.dirname(workspaceFolder.uri.fsPath));
83
84
const repository = this.model.getRepository(workspaceFolder.uri);
85
if (!repository) {
86
return;
87
}
88
89
await repository.status();
90
91
if (!repository.HEAD?.commit) {
92
// Handle publishing empty repository with no commits
93
94
const yes = vscode.l10n.t('Yes');
95
const selection = await vscode.window.showInformationMessage(
96
vscode.l10n.t('Would you like to publish this repository to continue working on it elsewhere?'),
97
{ modal: true },
98
yes
99
);
100
if (selection !== yes) {
101
throw new vscode.CancellationError();
102
}
103
await repository.commit('Initial commit', { all: true });
104
await vscode.commands.executeCommand('git.publish');
105
} else if (!repository.HEAD?.upstream && repository.HEAD?.type === RefType.Head) {
106
// If this branch hasn't been published to the remote yet,
107
// ensure that it is published before Continue On is invoked
108
109
const publishBranch = vscode.l10n.t('Publish Branch');
110
const selection = await vscode.window.showInformationMessage(
111
vscode.l10n.t('The current branch is not published to the remote. Would you like to publish it to access your changes elsewhere?'),
112
{ modal: true },
113
publishBranch
114
);
115
if (selection !== publishBranch) {
116
throw new vscode.CancellationError();
117
}
118
119
await vscode.commands.executeCommand('git.publish');
120
}
121
}
122
}
123
124
function normalizeEditSessionIdentity(identity: string) {
125
let { remote, ref, sha } = JSON.parse(identity);
126
127
if (typeof remote === 'string' && remote.endsWith('.git')) {
128
remote = remote.slice(0, remote.length - 4);
129
}
130
131
return {
132
remote,
133
ref,
134
sha
135
};
136
}
137
138