From 349e31fee9603711ddabfe4c8cb6fb66b72e28f3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 1 Nov 2018 15:00:36 +0100 Subject: [PATCH] fixes #58918 --- extensions/git/src/api/extension.ts | 64 ++++++++++++++++------------- extensions/git/src/api/git.d.ts | 7 ++++ extensions/git/src/main.ts | 13 +++--- extensions/git/src/util.ts | 12 ++++++ 4 files changed, 63 insertions(+), 33 deletions(-) diff --git a/extensions/git/src/api/extension.ts b/extensions/git/src/api/extension.ts index 1ca1892a7bd..8d7dc611e62 100644 --- a/extensions/git/src/api/extension.ts +++ b/extensions/git/src/api/extension.ts @@ -6,6 +6,8 @@ import { Model } from '../model'; import { GitExtension, Repository, API } from './git'; import { ApiRepository, ApiImpl } from './api1'; +import { Event, EventEmitter } from 'vscode'; +import { latchEvent } from '../util'; export function deprecated(_target: any, key: string, descriptor: any): void { if (typeof descriptor.value !== 'function') { @@ -19,50 +21,56 @@ export function deprecated(_target: any, key: string, descriptor: any): void { }; } -class NoModelGitExtension implements GitExtension { +export class GitExtensionImpl implements GitExtension { + + enabled: boolean = false; + + private _onDidChangeEnablement = new EventEmitter(); + readonly onDidChangeEnablement: Event = latchEvent(this._onDidChangeEnablement.event); + + private _model: Model | undefined = undefined; + + set model(model: Model | undefined) { + this._model = model; + + this.enabled = !!model; + this._onDidChangeEnablement.fire(this.enabled); + } + + constructor(model?: Model) { + if (model) { + this.enabled = true; + this._model = model; + } + } @deprecated async getGitPath(): Promise { - throw new Error('Git model not found'); - } + if (!this._model) { + throw new Error('Git model not found'); + } - @deprecated - async getRepositories(): Promise { - throw new Error('Git model not found'); - } - - getAPI(): API { - throw new Error('Git model not found'); - } -} - -class GitExtensionImpl implements GitExtension { - - constructor(private _model: Model) { } - - @deprecated - async getGitPath(): Promise { return this._model.git.path; } @deprecated async getRepositories(): Promise { + if (!this._model) { + throw new Error('Git model not found'); + } + return this._model.repositories.map(repository => new ApiRepository(repository)); } getAPI(version: number): API { + if (!this._model) { + throw new Error('Git model not found'); + } + if (version !== 1) { throw new Error(`No API version ${version} found.`); } return new ApiImpl(this._model); } -} - -export function createGitExtension(model?: Model): GitExtension { - if (!model) { - return new NoModelGitExtension(); - } - - return new GitExtensionImpl(model); -} +} \ No newline at end of file diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts index 77fff007cdc..8487a0823ed 100644 --- a/extensions/git/src/api/git.d.ts +++ b/extensions/git/src/api/git.d.ts @@ -164,9 +164,16 @@ export interface API { export interface GitExtension { + readonly enabled: boolean; + readonly onDidChangeEnablement: Event; + /** * Returns a specific API version. * + * Throws error if git extension is disabled. You can listed to the + * [GitExtension.onDidChangeEnablement](#GitExtension.onDidChangeEnablement) event + * to know when the extension becomes enabled/disabled. + * * @param version Version number. * @returns API instance */ diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index 1ff683150a5..52b7c3c106a 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -17,7 +17,7 @@ import { toDisposable, filterEvent, eventToPromise } from './util'; import TelemetryReporter from 'vscode-extension-telemetry'; import { GitExtension } from './api/git'; import { GitProtocolHandler } from './protocolHandler'; -import { createGitExtension } from './api/extension'; +import { GitExtensionImpl } from './api/extension'; import * as path from 'path'; import * as fs from 'fs'; @@ -137,12 +137,15 @@ export async function activate(context: ExtensionContext): Promise if (!enabled) { const onConfigChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git')); const onEnabled = filterEvent(onConfigChange, () => workspace.getConfiguration('git', null).get('enabled') === true); - await eventToPromise(onEnabled); + const result = new GitExtensionImpl(); + + eventToPromise(onEnabled).then(async () => result.model = await createModel(context, outputChannel, telemetryReporter, disposables)); + return result; } try { const model = await createModel(context, outputChannel, telemetryReporter, disposables); - return createGitExtension(model); + return new GitExtensionImpl(model); } catch (err) { if (!/Git installation not found/.test(err.message || '')) { throw err; @@ -151,9 +154,9 @@ export async function activate(context: ExtensionContext): Promise console.warn(err.message); outputChannel.appendLine(err.message); - await warnAboutMissingGit(); + warnAboutMissingGit(); - return createGitExtension(); + return new GitExtensionImpl(); } } diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index ea1ddb97abb..820397f02da 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -44,6 +44,18 @@ export function filterEvent(event: Event, filter: (e: T) => boolean): Even return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables); } +export function latchEvent(event: Event): Event { + let firstCall = true; + let cache: T; + + return filterEvent(event, value => { + let shouldEmit = firstCall || value !== cache; + firstCall = false; + cache = value; + return shouldEmit; + }); +} + export function anyEvent(...events: Event[]): Event { return (listener, thisArgs = null, disposables?) => { const result = combinedDisposable(events.map(event => event(i => listener.call(thisArgs, i))));