1.9 KB61 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {Logger} from 'isl-server/src/logger';
9import type {Disposable, Event} from 'vscode';
10
11import {EventEmitter, ThemeColor, Uri, window, type FileDecoration, type FileDecorationProvider} from 'vscode';
12import type {VSCodeRepo} from './VSCodeRepo';
13
14export default class IgnoredFileDecorationProvider implements FileDecorationProvider {
15 private readonly _onDidChangeDecorations = new EventEmitter<Uri[]>();
16 readonly onDidChangeFileDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
17
18 private disposables: Disposable[] = [];
19 // Cache: uri string → ignored boolean
20 private cache = new Map<string, boolean>();
21
22 constructor(
23 private repository: VSCodeRepo,
24 private logger: Logger,
25 ) {
26 this.disposables.push(window?.registerFileDecorationProvider?.(this));
27 }
28
29 provideFileDecoration(uri: Uri): FileDecoration | undefined | Thenable<FileDecoration | undefined> {
30 const root = this.repository.rootPath;
31 if (!uri.fsPath.startsWith(root)) {
32 return undefined;
33 }
34
35 const key = uri.toString();
36 if (this.cache.has(key)) {
37 return this.cache.get(key)
38 ? {color: new ThemeColor('gitDecoration.ignoredResourceForeground')}
39 : undefined;
40 }
41
42 const rel = uri.fsPath.slice(root.length + 1);
43 if (!rel || rel === '.sl') {
44 return undefined;
45 }
46
47 return this.repository.runSlCommand(['debugignore', rel]).then(result => {
48 if (result.exitCode !== 0) {
49 return undefined;
50 }
51 const ignored = result.stdout.includes(': ignored by');
52 this.cache.set(key, ignored);
53 return ignored ? {color: new ThemeColor('gitDecoration.ignoredResourceForeground')} : undefined;
54 });
55 }
56
57 dispose(): void {
58 this.disposables.forEach(d => d?.dispose());
59 }
60}
61