Skip to content

Commit 349e31f

Browse files
committed
1 parent b31b077 commit 349e31f

4 files changed

Lines changed: 59 additions & 29 deletions

File tree

extensions/git/src/api/extension.ts

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import { Model } from '../model';
77
import { GitExtension, Repository, API } from './git';
88
import { ApiRepository, ApiImpl } from './api1';
9+
import { Event, EventEmitter } from 'vscode';
10+
import { latchEvent } from '../util';
911

1012
export function deprecated(_target: any, key: string, descriptor: any): void {
1113
if (typeof descriptor.value !== 'function') {
@@ -19,50 +21,56 @@ export function deprecated(_target: any, key: string, descriptor: any): void {
1921
};
2022
}
2123

22-
class NoModelGitExtension implements GitExtension {
24+
export class GitExtensionImpl implements GitExtension {
2325

24-
@deprecated
25-
async getGitPath(): Promise<string> {
26-
throw new Error('Git model not found');
27-
}
26+
enabled: boolean = false;
2827

29-
@deprecated
30-
async getRepositories(): Promise<Repository[]> {
31-
throw new Error('Git model not found');
32-
}
28+
private _onDidChangeEnablement = new EventEmitter<boolean>();
29+
readonly onDidChangeEnablement: Event<boolean> = latchEvent(this._onDidChangeEnablement.event);
3330

34-
getAPI(): API {
35-
throw new Error('Git model not found');
36-
}
37-
}
31+
private _model: Model | undefined = undefined;
32+
33+
set model(model: Model | undefined) {
34+
this._model = model;
3835

39-
class GitExtensionImpl implements GitExtension {
36+
this.enabled = !!model;
37+
this._onDidChangeEnablement.fire(this.enabled);
38+
}
4039

41-
constructor(private _model: Model) { }
40+
constructor(model?: Model) {
41+
if (model) {
42+
this.enabled = true;
43+
this._model = model;
44+
}
45+
}
4246

4347
@deprecated
4448
async getGitPath(): Promise<string> {
49+
if (!this._model) {
50+
throw new Error('Git model not found');
51+
}
52+
4553
return this._model.git.path;
4654
}
4755

4856
@deprecated
4957
async getRepositories(): Promise<Repository[]> {
58+
if (!this._model) {
59+
throw new Error('Git model not found');
60+
}
61+
5062
return this._model.repositories.map(repository => new ApiRepository(repository));
5163
}
5264

5365
getAPI(version: number): API {
66+
if (!this._model) {
67+
throw new Error('Git model not found');
68+
}
69+
5470
if (version !== 1) {
5571
throw new Error(`No API version ${version} found.`);
5672
}
5773

5874
return new ApiImpl(this._model);
5975
}
60-
}
61-
62-
export function createGitExtension(model?: Model): GitExtension {
63-
if (!model) {
64-
return new NoModelGitExtension();
65-
}
66-
67-
return new GitExtensionImpl(model);
68-
}
76+
}

extensions/git/src/api/git.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,16 @@ export interface API {
164164

165165
export interface GitExtension {
166166

167+
readonly enabled: boolean;
168+
readonly onDidChangeEnablement: Event<boolean>;
169+
167170
/**
168171
* Returns a specific API version.
169172
*
173+
* Throws error if git extension is disabled. You can listed to the
174+
* [GitExtension.onDidChangeEnablement](#GitExtension.onDidChangeEnablement) event
175+
* to know when the extension becomes enabled/disabled.
176+
*
170177
* @param version Version number.
171178
* @returns API instance
172179
*/

extensions/git/src/main.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { toDisposable, filterEvent, eventToPromise } from './util';
1717
import TelemetryReporter from 'vscode-extension-telemetry';
1818
import { GitExtension } from './api/git';
1919
import { GitProtocolHandler } from './protocolHandler';
20-
import { createGitExtension } from './api/extension';
20+
import { GitExtensionImpl } from './api/extension';
2121
import * as path from 'path';
2222
import * as fs from 'fs';
2323

@@ -137,12 +137,15 @@ export async function activate(context: ExtensionContext): Promise<GitExtension>
137137
if (!enabled) {
138138
const onConfigChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git'));
139139
const onEnabled = filterEvent(onConfigChange, () => workspace.getConfiguration('git', null).get<boolean>('enabled') === true);
140-
await eventToPromise(onEnabled);
140+
const result = new GitExtensionImpl();
141+
142+
eventToPromise(onEnabled).then(async () => result.model = await createModel(context, outputChannel, telemetryReporter, disposables));
143+
return result;
141144
}
142145

143146
try {
144147
const model = await createModel(context, outputChannel, telemetryReporter, disposables);
145-
return createGitExtension(model);
148+
return new GitExtensionImpl(model);
146149
} catch (err) {
147150
if (!/Git installation not found/.test(err.message || '')) {
148151
throw err;
@@ -151,9 +154,9 @@ export async function activate(context: ExtensionContext): Promise<GitExtension>
151154
console.warn(err.message);
152155
outputChannel.appendLine(err.message);
153156

154-
await warnAboutMissingGit();
157+
warnAboutMissingGit();
155158

156-
return createGitExtension();
159+
return new GitExtensionImpl();
157160
}
158161
}
159162

extensions/git/src/util.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Even
4444
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
4545
}
4646

47+
export function latchEvent<T>(event: Event<T>): Event<T> {
48+
let firstCall = true;
49+
let cache: T;
50+
51+
return filterEvent(event, value => {
52+
let shouldEmit = firstCall || value !== cache;
53+
firstCall = false;
54+
cache = value;
55+
return shouldEmit;
56+
});
57+
}
58+
4759
export function anyEvent<T>(...events: Event<T>[]): Event<T> {
4860
return (listener, thisArgs = null, disposables?) => {
4961
const result = combinedDisposable(events.map(event => event(i => listener.call(thisArgs, i))));

0 commit comments

Comments
 (0)