mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 27ada910e121e23a6d95ecca9cae595fb98ab568
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Model } from '../model';
|
||||
import { Repository as BaseRepository, Resource } from '../repository';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, GitExtension, RefType, RemoteSourceProvider } from './git';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, GitExtension, RefType, RemoteSourceProvider, CredentialsProvider } from './git';
|
||||
import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands } from 'vscode';
|
||||
import { mapEvent } from '../util';
|
||||
import { toGitUri } from '../uri';
|
||||
@@ -183,6 +183,10 @@ export class ApiRepository implements Repository {
|
||||
return this._repository.removeRemote(name);
|
||||
}
|
||||
|
||||
renameRemote(name: string, newName: string): Promise<void> {
|
||||
return this._repository.renameRemote(name, newName);
|
||||
}
|
||||
|
||||
fetch(remote?: string | undefined, ref?: string | undefined, depth?: number | undefined): Promise<void> {
|
||||
return this._repository.fetch(remote, ref, depth);
|
||||
}
|
||||
@@ -248,10 +252,21 @@ export class ApiImpl implements API {
|
||||
return result ? new ApiRepository(result) : null;
|
||||
}
|
||||
|
||||
async init(root: Uri): Promise<Repository | null> {
|
||||
const path = root.fsPath;
|
||||
await this._model.git.init(path);
|
||||
await this._model.openRepository(path);
|
||||
return this.getRepository(root) || null;
|
||||
}
|
||||
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable {
|
||||
return this._model.registerRemoteSourceProvider(provider);
|
||||
}
|
||||
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
|
||||
return this._model.registerCredentialsProvider(provider);
|
||||
}
|
||||
|
||||
constructor(private _model: Model) { }
|
||||
}
|
||||
|
||||
|
||||
13
extensions/git/src/api/git.d.ts
vendored
13
extensions/git/src/api/git.d.ts
vendored
@@ -179,6 +179,7 @@ export interface Repository {
|
||||
|
||||
addRemote(name: string, url: string): Promise<void>;
|
||||
removeRemote(name: string): Promise<void>;
|
||||
renameRemote(name: string, newName: string): Promise<void>;
|
||||
|
||||
fetch(remote?: string, ref?: string, depth?: number): Promise<void>;
|
||||
pull(unshallow?: boolean): Promise<void>;
|
||||
@@ -203,6 +204,15 @@ export interface RemoteSourceProvider {
|
||||
getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
|
||||
}
|
||||
|
||||
export interface Credentials {
|
||||
readonly username: string;
|
||||
readonly password: string;
|
||||
}
|
||||
|
||||
export interface CredentialsProvider {
|
||||
getCredentials(host: Uri): ProviderResult<Credentials>;
|
||||
}
|
||||
|
||||
export type APIState = 'uninitialized' | 'initialized';
|
||||
|
||||
export interface API {
|
||||
@@ -215,7 +225,10 @@ export interface API {
|
||||
|
||||
toGitUri(uri: Uri, ref: string): Uri;
|
||||
getRepository(uri: Uri): Repository | null;
|
||||
init(root: Uri): Promise<Repository | null>;
|
||||
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable;
|
||||
}
|
||||
|
||||
export interface GitExtension {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
VSCODE_GIT_ASKPASS_PIPE=`mktemp`
|
||||
VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $*
|
||||
ELECTRON_RUN_AS_NODE="1" VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $*
|
||||
cat $VSCODE_GIT_ASKPASS_PIPE
|
||||
rm $VSCODE_GIT_ASKPASS_PIPE
|
||||
rm $VSCODE_GIT_ASKPASS_PIPE
|
||||
|
||||
@@ -3,36 +3,60 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { window, InputBoxOptions } from 'vscode';
|
||||
import { IDisposable } from './util';
|
||||
import { window, InputBoxOptions, Uri, OutputChannel, Disposable } from 'vscode';
|
||||
import { IDisposable, EmptyDisposable, toDisposable } from './util';
|
||||
import * as path from 'path';
|
||||
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
|
||||
|
||||
export interface AskpassEnvironment {
|
||||
GIT_ASKPASS: string;
|
||||
ELECTRON_RUN_AS_NODE?: string;
|
||||
VSCODE_GIT_ASKPASS_NODE?: string;
|
||||
VSCODE_GIT_ASKPASS_MAIN?: string;
|
||||
VSCODE_GIT_ASKPASS_HANDLE?: string;
|
||||
}
|
||||
import { IIPCHandler, IIPCServer, createIPCServer } from './ipc/ipcServer';
|
||||
import { CredentialsProvider, Credentials } from './api/git';
|
||||
|
||||
export class Askpass implements IIPCHandler {
|
||||
|
||||
private disposable: IDisposable;
|
||||
private disposable: IDisposable = EmptyDisposable;
|
||||
private cache = new Map<string, Credentials>();
|
||||
private credentialsProviders = new Set<CredentialsProvider>();
|
||||
|
||||
static getDisabledEnv(): AskpassEnvironment {
|
||||
return {
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
|
||||
};
|
||||
static async create(outputChannel: OutputChannel, context?: string): Promise<Askpass> {
|
||||
try {
|
||||
return new Askpass(await createIPCServer(context));
|
||||
} catch (err) {
|
||||
outputChannel.appendLine(`[error] Failed to create git askpass IPC: ${err}`);
|
||||
return new Askpass();
|
||||
}
|
||||
}
|
||||
|
||||
constructor(ipc: IIPCServer) {
|
||||
this.disposable = ipc.registerHandler('askpass', this);
|
||||
private constructor(private ipc?: IIPCServer) {
|
||||
if (ipc) {
|
||||
this.disposable = ipc.registerHandler('askpass', this);
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ request, host }: { request: string, host: string }): Promise<string> {
|
||||
const uri = Uri.parse(host);
|
||||
const authority = uri.authority.replace(/^.*@/, '');
|
||||
const password = /password/i.test(request);
|
||||
const cached = this.cache.get(authority);
|
||||
|
||||
if (cached && password) {
|
||||
this.cache.delete(authority);
|
||||
return cached.password;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
for (const credentialsProvider of this.credentialsProviders) {
|
||||
try {
|
||||
const credentials = await credentialsProvider.getCredentials(uri);
|
||||
|
||||
if (credentials) {
|
||||
this.cache.set(authority, credentials);
|
||||
setTimeout(() => this.cache.delete(authority), 60_000);
|
||||
return credentials.username;
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
const options: InputBoxOptions = {
|
||||
password: /password/i.test(request),
|
||||
password,
|
||||
placeHolder: request,
|
||||
prompt: `Git: ${host}`,
|
||||
ignoreFocusOut: true
|
||||
@@ -41,15 +65,26 @@ export class Askpass implements IIPCHandler {
|
||||
return await window.showInputBox(options) || '';
|
||||
}
|
||||
|
||||
getEnv(): AskpassEnvironment {
|
||||
getEnv(): { [key: string]: string; } {
|
||||
if (!this.ipc) {
|
||||
return {
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
ELECTRON_RUN_AS_NODE: '1',
|
||||
...this.ipc.getEnv(),
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
|
||||
VSCODE_GIT_ASKPASS_NODE: process.execPath,
|
||||
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js')
|
||||
};
|
||||
}
|
||||
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
|
||||
this.credentialsProviders.add(provider);
|
||||
return toDisposable(() => this.credentialsProviders.delete(provider));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposable.dispose();
|
||||
}
|
||||
|
||||
@@ -524,7 +524,7 @@ export class CommandCenter {
|
||||
quickpick.ignoreFocusOut = true;
|
||||
|
||||
const providers = this.model.getRemoteProviders()
|
||||
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {1}", provider.name), alwaysShow: true, provider }));
|
||||
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {0}", provider.name), alwaysShow: true, provider }));
|
||||
|
||||
quickpick.placeholder = providers.length === 0
|
||||
? localize('provide url', "Provide repository URL.")
|
||||
@@ -2560,6 +2560,14 @@ export class CommandCenter {
|
||||
type = 'warning';
|
||||
options.modal = false;
|
||||
break;
|
||||
case GitErrorCodes.AuthenticationFailed:
|
||||
const regex = /Authentication failed for '(.*)'/i;
|
||||
const match = regex.exec(err.stderr || String(err));
|
||||
|
||||
message = match
|
||||
? localize('auth failed specific', "Failed to authenticate to git remote:\n\n{0}", match[1])
|
||||
: localize('auth failed', "Failed to authenticate to git remote.");
|
||||
break;
|
||||
case GitErrorCodes.NoUserNameConfigured:
|
||||
case GitErrorCodes.NoUserEmailConfigured:
|
||||
message = localize('missing user info', "Make sure you configure your 'user.name' and 'user.email' in git.");
|
||||
|
||||
@@ -306,7 +306,7 @@ export interface IGitOptions {
|
||||
function getGitErrorCode(stderr: string): string | undefined {
|
||||
if (/Another git process seems to be running in this repository|If no other git process is currently running/.test(stderr)) {
|
||||
return GitErrorCodes.RepositoryIsLocked;
|
||||
} else if (/Authentication failed/.test(stderr)) {
|
||||
} else if (/Authentication failed/i.test(stderr)) {
|
||||
return GitErrorCodes.AuthenticationFailed;
|
||||
} else if (/Not a git repository/i.test(stderr)) {
|
||||
return GitErrorCodes.NotAGitRepository;
|
||||
@@ -1498,7 +1498,12 @@ export class Repository {
|
||||
}
|
||||
|
||||
async removeRemote(name: string): Promise<void> {
|
||||
const args = ['remote', 'rm', name];
|
||||
const args = ['remote', 'remove', name];
|
||||
await this.run(args);
|
||||
}
|
||||
|
||||
async renameRemote(name: string, newName: string): Promise<void> {
|
||||
const args = ['remote', 'rename', name, newName];
|
||||
await this.run(args);
|
||||
}
|
||||
|
||||
|
||||
66
extensions/git/src/github.ts
Normal file
66
extensions/git/src/github.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CredentialsProvider, Credentials } from './api/git';
|
||||
import { IDisposable, filterEvent, EmptyDisposable } from './util';
|
||||
import { workspace, Uri, AuthenticationSession, authentication } from 'vscode';
|
||||
import { Askpass } from './askpass';
|
||||
|
||||
export class GitHubCredentialProvider implements CredentialsProvider {
|
||||
|
||||
async getCredentials(host: Uri): Promise<Credentials | undefined> {
|
||||
if (!/github\.com/i.test(host.authority)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const session = await this.getSession();
|
||||
return { username: session.account.id, password: await session.getAccessToken() };
|
||||
}
|
||||
|
||||
private async getSession(): Promise<AuthenticationSession> {
|
||||
const authenticationSessions = await authentication.getSessions('github', ['repo']);
|
||||
|
||||
if (authenticationSessions.length) {
|
||||
return await authenticationSessions[0];
|
||||
} else {
|
||||
return await authentication.login('github', ['repo']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class GithubCredentialProviderManager {
|
||||
|
||||
private providerDisposable: IDisposable = EmptyDisposable;
|
||||
private readonly disposable: IDisposable;
|
||||
|
||||
private _enabled = false;
|
||||
private set enabled(enabled: boolean) {
|
||||
if (this._enabled === enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._enabled = enabled;
|
||||
|
||||
if (enabled) {
|
||||
this.providerDisposable = this.askpass.registerCredentialsProvider(new GitHubCredentialProvider());
|
||||
} else {
|
||||
this.providerDisposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private readonly askpass: Askpass) {
|
||||
this.disposable = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git'))(this.refresh, this);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
private refresh(): void {
|
||||
this.enabled = workspace.getConfiguration('git', null).get('githubAuthentication', true);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.enabled = false;
|
||||
this.disposable.dispose();
|
||||
}
|
||||
}
|
||||
@@ -11,27 +11,42 @@ import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
function getIPCHandlePath(nonce: string): string {
|
||||
function getIPCHandlePath(id: string): string {
|
||||
if (process.platform === 'win32') {
|
||||
return `\\\\.\\pipe\\vscode-git-ipc-${nonce}-sock`;
|
||||
return `\\\\.\\pipe\\vscode-git-${id}-sock`;
|
||||
}
|
||||
|
||||
if (process.env['XDG_RUNTIME_DIR']) {
|
||||
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-ipc-${nonce}.sock`);
|
||||
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-${id}.sock`);
|
||||
}
|
||||
|
||||
return path.join(os.tmpdir(), `vscode-git-ipc-${nonce}.sock`);
|
||||
return path.join(os.tmpdir(), `vscode-git-${id}.sock`);
|
||||
}
|
||||
|
||||
export interface IIPCHandler {
|
||||
handle(request: any): Promise<any>;
|
||||
}
|
||||
|
||||
export async function createIPCServer(): Promise<IIPCServer> {
|
||||
export async function createIPCServer(context?: string): Promise<IIPCServer> {
|
||||
const server = http.createServer();
|
||||
const buffer = await new Promise<Buffer>((c, e) => crypto.randomBytes(20, (err, buf) => err ? e(err) : c(buf)));
|
||||
const nonce = buffer.toString('hex');
|
||||
const ipcHandlePath = getIPCHandlePath(nonce);
|
||||
const hash = crypto.createHash('sha1');
|
||||
|
||||
if (!context) {
|
||||
const buffer = await new Promise<Buffer>((c, e) => crypto.randomBytes(20, (err, buf) => err ? e(err) : c(buf)));
|
||||
hash.update(buffer);
|
||||
} else {
|
||||
hash.update(context);
|
||||
}
|
||||
|
||||
const ipcHandlePath = getIPCHandlePath(hash.digest('hex').substr(0, 10));
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
try {
|
||||
await fs.promises.unlink(ipcHandlePath);
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((c, e) => {
|
||||
try {
|
||||
@@ -46,7 +61,7 @@ export async function createIPCServer(): Promise<IIPCServer> {
|
||||
|
||||
export interface IIPCServer extends Disposable {
|
||||
readonly ipcHandlePath: string | undefined;
|
||||
getEnv(): any;
|
||||
getEnv(): { [key: string]: string; };
|
||||
registerHandler(name: string, handler: IIPCHandler): Disposable;
|
||||
}
|
||||
|
||||
@@ -91,7 +106,7 @@ class IPCServer implements IIPCServer, Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
getEnv(): any {
|
||||
getEnv(): { [key: string]: string; } {
|
||||
return { VSCODE_GIT_IPC_HANDLE: this.ipcHandlePath };
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,10 @@ import { GitProtocolHandler } from './protocolHandler';
|
||||
import { GitExtensionImpl } from './api/extension';
|
||||
// import * as path from 'path';
|
||||
// import * as fs from 'fs';
|
||||
import { createIPCServer, IIPCServer } from './ipc/ipcServer';
|
||||
import { GitTimelineProvider } from './timelineProvider';
|
||||
import { registerAPICommands } from './api/api1';
|
||||
import { GithubCredentialProviderManager } from './github';
|
||||
import { TerminalEnvironmentManager } from './terminal';
|
||||
|
||||
const deactivateTasks: { (): Promise<any>; }[] = [];
|
||||
|
||||
@@ -36,27 +37,18 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
const pathHint = workspace.getConfiguration('git').get<string>('path');
|
||||
const info = await findGit(pathHint, path => outputChannel.appendLine(localize('looking', "Looking for git in: {0}", path)));
|
||||
|
||||
let env: any = {};
|
||||
let ipc: IIPCServer | undefined;
|
||||
const askpass = await Askpass.create(outputChannel, context.storagePath);
|
||||
disposables.push(askpass);
|
||||
|
||||
try {
|
||||
ipc = await createIPCServer();
|
||||
disposables.push(ipc);
|
||||
env = { ...env, ...ipc.getEnv() };
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
const env = askpass.getEnv();
|
||||
const terminalEnvironmentManager = new TerminalEnvironmentManager(context, env);
|
||||
disposables.push(terminalEnvironmentManager);
|
||||
|
||||
if (ipc) {
|
||||
const askpass = new Askpass(ipc);
|
||||
disposables.push(askpass);
|
||||
env = { ...env, ...askpass.getEnv() };
|
||||
} else {
|
||||
env = { ...env, ...Askpass.getDisabledEnv() };
|
||||
}
|
||||
const githubCredentialProviderManager = new GithubCredentialProviderManager(askpass);
|
||||
context.subscriptions.push(githubCredentialProviderManager);
|
||||
|
||||
const git = new Git({ gitPath: info.path, version: info.version, env });
|
||||
const model = new Model(git, context.globalState, outputChannel);
|
||||
const model = new Model(git, askpass, context.globalState, outputChannel);
|
||||
disposables.push(model);
|
||||
|
||||
const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`);
|
||||
|
||||
@@ -12,7 +12,8 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { fromGitUri } from './uri';
|
||||
import { GitErrorCodes, APIState as State, RemoteSourceProvider } from './api/git';
|
||||
import { GitErrorCodes, APIState as State, RemoteSourceProvider, CredentialsProvider } from './api/git';
|
||||
import { Askpass } from './askpass';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -78,7 +79,7 @@ export class Model {
|
||||
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
|
||||
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel) {
|
||||
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
|
||||
window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables);
|
||||
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables);
|
||||
@@ -454,6 +455,10 @@ export class Model {
|
||||
return toDisposable(() => this.remoteProviders.delete(provider));
|
||||
}
|
||||
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
|
||||
return this.askpass.registerCredentialsProvider(provider);
|
||||
}
|
||||
|
||||
getRemoteProviders(): RemoteSourceProvider[] {
|
||||
return [...this.remoteProviders.values()];
|
||||
}
|
||||
|
||||
@@ -1096,6 +1096,10 @@ export class Repository implements Disposable {
|
||||
await this.run(Operation.Remote, () => this.repository.removeRemote(name));
|
||||
}
|
||||
|
||||
async renameRemote(name: string, newName: string): Promise<void> {
|
||||
await this.run(Operation.Remote, () => this.repository.renameRemote(name, newName));
|
||||
}
|
||||
|
||||
@throttle
|
||||
async fetchDefault(options: { silent?: boolean } = {}): Promise<void> {
|
||||
await this.run(Operation.Fetch, () => this.repository.fetch(options));
|
||||
|
||||
43
extensions/git/src/terminal.ts
Normal file
43
extensions/git/src/terminal.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtensionContext, workspace } from 'vscode';
|
||||
import { filterEvent, IDisposable } from './util';
|
||||
|
||||
export class TerminalEnvironmentManager {
|
||||
|
||||
private readonly disposable: IDisposable;
|
||||
|
||||
private _enabled = false;
|
||||
private set enabled(enabled: boolean) {
|
||||
if (this._enabled === enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._enabled = enabled;
|
||||
this.context.environmentVariableCollection.clear();
|
||||
|
||||
if (enabled) {
|
||||
for (const name of Object.keys(this.env)) {
|
||||
this.context.environmentVariableCollection.replace(name, this.env[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private readonly context: ExtensionContext, private readonly env: { [key: string]: string }) {
|
||||
this.disposable = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git'))
|
||||
(this.refresh, this);
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
private refresh(): void {
|
||||
this.enabled = workspace.getConfiguration('git', null).get('terminalAuthentication', true);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposable.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user