forked from microsoft/vscode-pull-request-github
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtemporaryState.ts
More file actions
143 lines (122 loc) · 5.21 KB
/
Copy pathtemporaryState.ts
File metadata and controls
143 lines (122 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { disposeAll } from './lifecycle';
import Logger from './logger';
import { isDescendant } from './utils';
let tempState: TemporaryState | undefined;
export class TemporaryState extends vscode.Disposable {
static readonly ID = 'TemporaryState';
private readonly SUBPATH = 'temp';
private readonly disposables: vscode.Disposable[] = [];
private readonly persistInSessionDisposables: vscode.Disposable[] = [];
constructor(private readonly _storageUri: vscode.Uri) {
super(() => disposeAll(this.disposables));
}
private get path(): vscode.Uri {
return vscode.Uri.joinPath(this._storageUri, this.SUBPATH);
}
override dispose() {
disposeAll(this.disposables);
disposeAll(this.persistInSessionDisposables);
}
private addDisposable(disposable: vscode.Disposable, persistInSession: boolean) {
if (persistInSession) {
this.persistInSessionDisposables.push(disposable);
} else {
if (this.disposables.length > 30) {
const oldDisposable = this.disposables.shift();
oldDisposable?.dispose();
}
this.disposables.push(disposable);
}
}
private async writeState(subpath: string, filename: string, contents: Uint8Array, persistInSession: boolean, repositoryUri: vscode.Uri): Promise<vscode.Uri> {
let filePath: vscode.Uri = this.path;
let workspace: string | undefined;
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
const matchingFolder = vscode.workspace.workspaceFolders.find(folder =>
isDescendant(folder.uri.fsPath, repositoryUri.fsPath) || isDescendant(repositoryUri.fsPath, folder.uri.fsPath)
);
workspace = matchingFolder?.name;
}
// Fall back to the first workspace folder if no match found
if (!workspace && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
workspace = vscode.workspace.workspaceFolders[0].name;
}
if (workspace) {
filePath = vscode.Uri.joinPath(filePath, workspace);
}
if (subpath) {
filePath = vscode.Uri.joinPath(filePath, subpath);
}
await vscode.workspace.fs.createDirectory(filePath);
const file = vscode.Uri.joinPath(filePath, filename);
await vscode.workspace.fs.writeFile(file, contents);
const dispose = {
dispose: () => {
try {
return vscode.workspace.fs.delete(file, { recursive: true });
} catch (e) {
// No matter the error, we do not want to throw in dispose.
}
}
};
this.addDisposable(dispose, persistInSession);
return file;
}
private async readState(subpath: string, filename: string, repositoryUri: vscode.Uri): Promise<Uint8Array> {
let filePath: vscode.Uri = this.path;
let workspace: string | undefined;
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
const matchingFolder = vscode.workspace.workspaceFolders.find(folder =>
isDescendant(folder.uri.fsPath, repositoryUri.fsPath) || isDescendant(repositoryUri.fsPath, folder.uri.fsPath)
);
workspace = matchingFolder?.name;
}
// Fall back to the first workspace folder if no match found
if (!workspace && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
workspace = vscode.workspace.workspaceFolders[0].name;
}
if (workspace) {
filePath = vscode.Uri.joinPath(filePath, workspace);
}
filePath = vscode.Uri.joinPath(filePath, subpath);
const file = vscode.Uri.joinPath(filePath, filename);
return vscode.workspace.fs.readFile(file);
}
static async init(context: vscode.ExtensionContext): Promise<vscode.Disposable | undefined> {
if (context.globalStorageUri && !tempState) {
tempState = new TemporaryState(context.globalStorageUri);
try {
await vscode.workspace.fs.delete(tempState.path, { recursive: true });
} catch (e) {
// Ignore FileNotFound errors - the temp directory may not exist yet on first run.
if (!(e instanceof vscode.FileSystemError) || e.code !== 'FileNotFound') {
Logger.appendLine(`Error in initialization: ${e.message}`, TemporaryState.ID);
}
}
try {
await vscode.workspace.fs.createDirectory(tempState.path);
} catch (e) {
Logger.appendLine(`Error in initialization: ${e.message}`, TemporaryState.ID);
}
context.subscriptions.push(tempState);
return tempState;
}
}
static async write(subpath: string, filename: string, contents: Uint8Array, persistInSession: boolean = false, repositoryUri: vscode.Uri): Promise<vscode.Uri | undefined> {
if (!tempState) {
return;
}
return tempState.writeState(subpath, filename, contents, persistInSession, repositoryUri);
}
static async read(subpath: string, filename: string, repositoryUri: vscode.Uri): Promise<Uint8Array | undefined> {
if (!tempState) {
return;
}
return tempState.readState(subpath, filename, repositoryUri);
}
}