Skip to content

Commit fad4d8d

Browse files
committed
1 parent 85677ae commit fad4d8d

2 files changed

Lines changed: 56 additions & 23 deletions

File tree

extensions/git/src/decorationProvider.ts

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ import * as path from 'path';
88
import { Repository, GitResourceGroup } from './repository';
99
import { Model } from './model';
1010
import { debounce } from './decorators';
11-
import { filterEvent, dispose, anyEvent, fireEvent } from './util';
11+
import { filterEvent, dispose, anyEvent, fireEvent, PromiseSource } from './util';
1212
import { GitErrorCodes, Status } from './api/git';
1313

14-
type Callback = { resolve: (status: boolean) => void, reject: (err: any) => void };
15-
1614
class GitIgnoreDecorationProvider implements DecorationProvider {
1715

16+
private static Decoration: Decoration = { priority: 3, color: new ThemeColor('gitDecoration.ignoredResourceForeground') };
17+
1818
readonly onDidChangeDecorations: Event<Uri[]>;
19-
private queue = new Map<string, { repository: Repository; queue: Map<string, Callback>; }>();
19+
private queue = new Map<string, { repository: Repository; queue: Map<string, PromiseSource<Decoration | undefined>>; }>();
2020
private disposables: Disposable[] = [];
2121

2222
constructor(private model: Model) {
@@ -29,32 +29,29 @@ class GitIgnoreDecorationProvider implements DecorationProvider {
2929
this.disposables.push(window.registerDecorationProvider(this));
3030
}
3131

32-
provideDecoration(uri: Uri): Promise<Decoration | undefined> {
32+
async provideDecoration(uri: Uri): Promise<Decoration | undefined> {
3333
const repository = this.model.getRepository(uri);
3434

3535
if (!repository) {
36-
return Promise.resolve(undefined);
36+
return;
3737
}
3838

3939
let queueItem = this.queue.get(repository.root);
4040

4141
if (!queueItem) {
42-
queueItem = { repository, queue: new Map<string, Callback>() };
42+
queueItem = { repository, queue: new Map<string, PromiseSource<Decoration | undefined>>() };
4343
this.queue.set(repository.root, queueItem);
4444
}
4545

46-
return new Promise<boolean>((resolve, reject) => {
47-
queueItem!.queue.set(uri.fsPath, { resolve, reject });
46+
let promiseSource = queueItem.queue.get(uri.fsPath);
47+
48+
if (!promiseSource) {
49+
promiseSource = new PromiseSource();
50+
queueItem!.queue.set(uri.fsPath, promiseSource);
4851
this.checkIgnoreSoon();
49-
}).then(ignored => {
50-
if (ignored) {
51-
return <Decoration>{
52-
priority: 3,
53-
color: new ThemeColor('gitDecoration.ignoredResourceForeground')
54-
};
55-
}
56-
return undefined;
57-
});
52+
}
53+
54+
return await promiseSource.promise;
5855
}
5956

6057
@debounce(500)
@@ -66,16 +63,16 @@ class GitIgnoreDecorationProvider implements DecorationProvider {
6663
const paths = [...item.queue.keys()];
6764

6865
item.repository.checkIgnore(paths).then(ignoreSet => {
69-
for (const [key, value] of item.queue.entries()) {
70-
value.resolve(ignoreSet.has(key));
66+
for (const [path, promiseSource] of item.queue.entries()) {
67+
promiseSource.resolve(ignoreSet.has(path) ? GitIgnoreDecorationProvider.Decoration : undefined);
7168
}
7269
}, err => {
7370
if (err.gitErrorCode !== GitErrorCodes.IsInSubmodule) {
7471
console.error(err);
7572
}
7673

77-
for (const [, value] of item.queue.entries()) {
78-
value.reject(err);
74+
for (const [, promiseSource] of item.queue.entries()) {
75+
promiseSource.reject(err);
7976
}
8077
});
8178
}

extensions/git/src/util.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { Event, Disposable } from 'vscode';
6+
import { Event, Disposable, EventEmitter } from 'vscode';
77
import { dirname, sep } from 'path';
88
import { Readable } from 'stream';
99
import { promises as fs, createReadStream } from 'fs';
@@ -400,3 +400,39 @@ export class Limiter<T> {
400400
}
401401
}
402402
}
403+
404+
type Completion<T> = { success: true, value: T } | { success: false, err: any };
405+
406+
export class PromiseSource<T> {
407+
408+
private _onDidComplete = new EventEmitter<Completion<T>>();
409+
410+
private _promise: Promise<T> | undefined;
411+
get promise(): Promise<T> {
412+
if (this._promise) {
413+
return this._promise;
414+
}
415+
416+
return eventToPromise(this._onDidComplete.event).then(completion => {
417+
if (completion.success) {
418+
return completion.value;
419+
} else {
420+
throw completion.err;
421+
}
422+
});
423+
}
424+
425+
resolve(value: T): void {
426+
if (!this._promise) {
427+
this._promise = Promise.resolve(value);
428+
this._onDidComplete.fire({ success: true, value });
429+
}
430+
}
431+
432+
reject(err: any): void {
433+
if (!this._promise) {
434+
this._promise = Promise.reject(err);
435+
this._onDidComplete.fire({ success: false, err });
436+
}
437+
}
438+
}

0 commit comments

Comments
 (0)