@theia/workspace 1.68.0 → 1.68.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/metadata-storage/index.d.ts +18 -0
- package/lib/browser/metadata-storage/index.d.ts.map +1 -0
- package/lib/browser/metadata-storage/index.js +25 -0
- package/lib/browser/metadata-storage/index.js.map +1 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.d.ts +94 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.d.ts.map +1 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.js +191 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.js.map +1 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.spec.d.ts +17 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.spec.d.ts.map +1 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.spec.js +279 -0
- package/lib/browser/metadata-storage/workspace-metadata-storage-service.spec.js.map +1 -0
- package/lib/browser/metadata-storage/workspace-metadata-store.d.ts +81 -0
- package/lib/browser/metadata-storage/workspace-metadata-store.d.ts.map +1 -0
- package/lib/browser/metadata-storage/workspace-metadata-store.js +137 -0
- package/lib/browser/metadata-storage/workspace-metadata-store.js.map +1 -0
- package/lib/browser/workspace-frontend-module.d.ts.map +1 -1
- package/lib/browser/workspace-frontend-module.js +6 -0
- package/lib/browser/workspace-frontend-module.js.map +1 -1
- package/lib/browser/workspace-trust-service.d.ts.map +1 -1
- package/lib/browser/workspace-trust-service.js +4 -4
- package/lib/browser/workspace-trust-service.js.map +1 -1
- package/package.json +6 -6
- package/src/browser/index.ts +1 -0
- package/src/browser/metadata-storage/index.ts +23 -0
- package/src/browser/metadata-storage/workspace-metadata-storage-service.spec.ts +342 -0
- package/src/browser/metadata-storage/workspace-metadata-storage-service.ts +244 -0
- package/src/browser/metadata-storage/workspace-metadata-store.ts +172 -0
- package/src/browser/workspace-frontend-module.ts +7 -0
- package/src/browser/workspace-trust-service.ts +4 -5
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
|
18
|
+
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
19
|
+
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
|
20
|
+
import { ILogger } from '@theia/core/lib/common/logger';
|
|
21
|
+
import { URI } from '@theia/core/lib/common/uri';
|
|
22
|
+
import { generateUuid } from '@theia/core/lib/common/uuid';
|
|
23
|
+
import { BinaryBuffer } from '@theia/core/lib/common/buffer';
|
|
24
|
+
import { WorkspaceService } from '../workspace-service';
|
|
25
|
+
import { WorkspaceMetadataStore, WorkspaceMetadataStoreImpl } from './workspace-metadata-store';
|
|
26
|
+
|
|
27
|
+
export const WorkspaceMetadataStoreFactory = Symbol('WorkspaceMetadataStoreFactory');
|
|
28
|
+
export type WorkspaceMetadataStoreFactory = () => WorkspaceMetadataStoreImpl;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Index mapping workspace root paths to UUIDs.
|
|
32
|
+
* Stored at $CONFIGDIR/workspace-metadata/index.json
|
|
33
|
+
*/
|
|
34
|
+
export interface WorkspaceMetadataIndex {
|
|
35
|
+
[workspacePath: string]: string; // workspace path -> UUID
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Service for managing workspace-specific metadata storage.
|
|
40
|
+
* Provides isolated storage directories for different features within a workspace.
|
|
41
|
+
*
|
|
42
|
+
* This is different to the `WorkspaceStorageService` in that it is an unlimited free-form
|
|
43
|
+
* storage area _in the filesystem_ and not in the browser's local storage.
|
|
44
|
+
*/
|
|
45
|
+
export const WorkspaceMetadataStorageService = Symbol('WorkspaceMetadataStorageService');
|
|
46
|
+
export interface WorkspaceMetadataStorageService {
|
|
47
|
+
/**
|
|
48
|
+
* Gets an existing metadata store for the given key, or creates a new one if it doesn't exist.
|
|
49
|
+
*
|
|
50
|
+
* @param key A unique identifier for the metadata store. Special characters will be replaced with hyphens.
|
|
51
|
+
* @returns The existing or newly created WorkspaceMetadataStore instance
|
|
52
|
+
* @throws Error if no workspace is currently open
|
|
53
|
+
*/
|
|
54
|
+
getOrCreateStore(key: string): Promise<WorkspaceMetadataStore>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@injectable()
|
|
58
|
+
export class WorkspaceMetadataStorageServiceImpl implements WorkspaceMetadataStorageService {
|
|
59
|
+
|
|
60
|
+
@inject(FileService)
|
|
61
|
+
protected readonly fileService: FileService;
|
|
62
|
+
|
|
63
|
+
@inject(WorkspaceService)
|
|
64
|
+
protected readonly workspaceService: WorkspaceService;
|
|
65
|
+
|
|
66
|
+
@inject(EnvVariablesServer)
|
|
67
|
+
protected readonly envVariableServer: EnvVariablesServer;
|
|
68
|
+
|
|
69
|
+
@inject(ILogger) @named('WorkspaceMetadataStorage')
|
|
70
|
+
protected readonly logger: ILogger;
|
|
71
|
+
|
|
72
|
+
@inject(WorkspaceMetadataStoreFactory)
|
|
73
|
+
protected readonly storeFactory: WorkspaceMetadataStoreFactory;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Registry of created stores by their mangled keys
|
|
77
|
+
*/
|
|
78
|
+
protected readonly stores = new Map<string, WorkspaceMetadataStore>();
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Cached metadata root directory (e.g., file://$CONFIGDIR/workspace-metadata/)
|
|
82
|
+
*/
|
|
83
|
+
protected metadataRoot?: URI;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Cached index file location
|
|
87
|
+
*/
|
|
88
|
+
protected indexFile?: URI;
|
|
89
|
+
|
|
90
|
+
async getOrCreateStore(key: string): Promise<WorkspaceMetadataStore> {
|
|
91
|
+
const mangledKey = this.mangleKey(key);
|
|
92
|
+
|
|
93
|
+
const existingStore = this.stores.get(mangledKey);
|
|
94
|
+
if (existingStore) {
|
|
95
|
+
this.logger.debug(`Returning existing metadata store for key '${key}'`, {
|
|
96
|
+
mangledKey,
|
|
97
|
+
location: existingStore.location.toString()
|
|
98
|
+
});
|
|
99
|
+
return existingStore;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return this.doCreateStore(key, mangledKey);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
protected async doCreateStore(key: string, mangledKey: string): Promise<WorkspaceMetadataStore> {
|
|
106
|
+
const workspaceRoot = this.getFirstWorkspaceRoot();
|
|
107
|
+
if (!workspaceRoot) {
|
|
108
|
+
throw new Error('Cannot create metadata store: no workspace is currently open');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const workspaceUuid = await this.getOrCreateWorkspaceUUID(workspaceRoot);
|
|
112
|
+
const storeLocation = await this.getStoreLocation(workspaceUuid, mangledKey);
|
|
113
|
+
const store = this.storeFactory();
|
|
114
|
+
|
|
115
|
+
store.initialize(
|
|
116
|
+
mangledKey,
|
|
117
|
+
storeLocation,
|
|
118
|
+
async () => this.resolveStoreLocation(mangledKey),
|
|
119
|
+
() => this.stores.delete(mangledKey)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
this.stores.set(mangledKey, store);
|
|
123
|
+
|
|
124
|
+
this.logger.debug(`Created metadata store for key '${key}'`, {
|
|
125
|
+
mangledKey,
|
|
126
|
+
location: storeLocation.toString()
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return store;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Mangles a key to make it safe for use as a directory name.
|
|
134
|
+
* Replaces all characters except alphanumerics, hyphens, and underscores with hyphens.
|
|
135
|
+
*/
|
|
136
|
+
protected mangleKey(key: string): string {
|
|
137
|
+
return key.replace(/[^a-zA-Z0-9-_]/g, '-');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
protected getFirstWorkspaceRoot(): URI | undefined {
|
|
141
|
+
const roots = this.workspaceService.tryGetRoots();
|
|
142
|
+
return roots.length > 0 ? roots[0].resource : undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Gets or creates a UUID for the given workspace root.
|
|
147
|
+
* UUIDs are stored in an index file and reused if the same workspace is opened again.
|
|
148
|
+
*/
|
|
149
|
+
protected async getOrCreateWorkspaceUUID(workspaceRoot: URI): Promise<string> {
|
|
150
|
+
const index = await this.loadIndex();
|
|
151
|
+
const workspacePath = workspaceRoot.path.toString();
|
|
152
|
+
|
|
153
|
+
if (index[workspacePath]) {
|
|
154
|
+
return index[workspacePath];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const newUuid = generateUuid();
|
|
158
|
+
index[workspacePath] = newUuid;
|
|
159
|
+
|
|
160
|
+
await this.saveIndex(index);
|
|
161
|
+
|
|
162
|
+
this.logger.debug('Generated new UUID for workspace', {
|
|
163
|
+
workspacePath,
|
|
164
|
+
uuid: newUuid
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return newUuid;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
protected async loadIndex(): Promise<WorkspaceMetadataIndex> {
|
|
171
|
+
const indexFileUri = await this.getIndexFile();
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const exists = await this.fileService.exists(indexFileUri);
|
|
175
|
+
if (!exists) {
|
|
176
|
+
return {};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const content = await this.fileService.readFile(indexFileUri);
|
|
180
|
+
return JSON.parse(content.value.toString()) as WorkspaceMetadataIndex;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
this.logger.warn('Failed to load workspace metadata index, using empty index', error);
|
|
183
|
+
return {};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
protected async saveIndex(index: WorkspaceMetadataIndex): Promise<void> {
|
|
188
|
+
const indexFileUri = await this.getIndexFile();
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
// Ensure metadata root exists
|
|
192
|
+
const metadataRootUri = await this.getMetadataRoot();
|
|
193
|
+
await this.fileService.createFolder(metadataRootUri);
|
|
194
|
+
|
|
195
|
+
// Write index file
|
|
196
|
+
const content = JSON.stringify(index, undefined, 2);
|
|
197
|
+
await this.fileService.writeFile(
|
|
198
|
+
indexFileUri,
|
|
199
|
+
BinaryBuffer.fromString(content)
|
|
200
|
+
);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
this.logger.error('Failed to save workspace metadata index', error);
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
protected async getMetadataRoot(): Promise<URI> {
|
|
208
|
+
if (!this.metadataRoot) {
|
|
209
|
+
const configDirUri = await this.envVariableServer.getConfigDirUri();
|
|
210
|
+
this.metadataRoot = new URI(configDirUri).resolve('workspace-metadata');
|
|
211
|
+
}
|
|
212
|
+
return this.metadataRoot;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
protected async getIndexFile(): Promise<URI> {
|
|
216
|
+
if (!this.indexFile) {
|
|
217
|
+
const metadataRoot = await this.getMetadataRoot();
|
|
218
|
+
this.indexFile = metadataRoot.resolve('index.json');
|
|
219
|
+
}
|
|
220
|
+
return this.indexFile;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Gets the location for a store given a workspace UUID and mangled key.
|
|
225
|
+
*/
|
|
226
|
+
protected async getStoreLocation(workspaceUuid: string, mangledKey: string): Promise<URI> {
|
|
227
|
+
const metadataRoot = await this.getMetadataRoot();
|
|
228
|
+
return metadataRoot.resolve(workspaceUuid).resolve(mangledKey);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Resolves the current store location for a given mangled key.
|
|
233
|
+
* Used when workspace changes to get the new location.
|
|
234
|
+
*/
|
|
235
|
+
protected async resolveStoreLocation(mangledKey: string): Promise<URI> {
|
|
236
|
+
const workspaceRoot = this.getFirstWorkspaceRoot();
|
|
237
|
+
if (!workspaceRoot) {
|
|
238
|
+
throw new Error('No workspace is currently open');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const workspaceUuid = await this.getOrCreateWorkspaceUUID(workspaceRoot);
|
|
242
|
+
return this.getStoreLocation(workspaceUuid, mangledKey);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
import { inject, injectable, named, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
+
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
19
|
+
import { ILogger, Emitter, Event, Disposable, DisposableCollection, URI } from '@theia/core/lib/common';
|
|
20
|
+
import { WorkspaceService } from '../workspace-service';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Represents a metadata store for a specific key within a workspace.
|
|
24
|
+
* The store provides access to a dedicated directory for storing workspace-specific metadata.
|
|
25
|
+
*/
|
|
26
|
+
export interface WorkspaceMetadataStore extends Disposable {
|
|
27
|
+
/**
|
|
28
|
+
* The key identifying this metadata store.
|
|
29
|
+
*/
|
|
30
|
+
readonly key: string;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The URI location of the metadata store directory.
|
|
34
|
+
*/
|
|
35
|
+
readonly location: URI;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Event that fires when the location of the metadata store changes.
|
|
39
|
+
* It is the client's responsibility to reload or reinitialize any metadata from
|
|
40
|
+
* or in the new location.
|
|
41
|
+
*/
|
|
42
|
+
readonly onDidChangeLocation: Event<URI>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Ensures that the metadata store directory exists on disk.
|
|
46
|
+
* Creates the directory if it doesn't exist.
|
|
47
|
+
*/
|
|
48
|
+
ensureExists(): Promise<void>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Deletes the metadata store directory and all of its contents.
|
|
52
|
+
*/
|
|
53
|
+
delete(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Implementation of WorkspaceMetadataStore.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
@injectable()
|
|
61
|
+
export class WorkspaceMetadataStoreImpl implements WorkspaceMetadataStore {
|
|
62
|
+
|
|
63
|
+
@inject(FileService)
|
|
64
|
+
protected readonly fileService: FileService;
|
|
65
|
+
|
|
66
|
+
@inject(WorkspaceService)
|
|
67
|
+
protected readonly workspaceService: WorkspaceService;
|
|
68
|
+
|
|
69
|
+
@inject(ILogger) @named('WorkspaceMetadataStorage')
|
|
70
|
+
protected readonly logger: ILogger;
|
|
71
|
+
|
|
72
|
+
protected readonly toDispose = new DisposableCollection();
|
|
73
|
+
|
|
74
|
+
protected readonly onDidChangeLocationEmitter = new Emitter<URI>();
|
|
75
|
+
readonly onDidChangeLocation: Event<URI> = this.onDidChangeLocationEmitter.event;
|
|
76
|
+
|
|
77
|
+
protected _location: URI;
|
|
78
|
+
protected _key: string;
|
|
79
|
+
protected currentWorkspaceRoot?: URI;
|
|
80
|
+
protected locationProvider: () => Promise<URI>;
|
|
81
|
+
protected onDisposeCallback?: () => void;
|
|
82
|
+
|
|
83
|
+
get location(): URI {
|
|
84
|
+
return this._location;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get key(): string {
|
|
88
|
+
return this._key;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Initializes the WorkspaceMetadataStore.
|
|
93
|
+
* @param key The key identifying this store
|
|
94
|
+
* @param initialLocation The initial location URI
|
|
95
|
+
* @param locationProvider Function to resolve the current location based on workspace changes
|
|
96
|
+
* @param onDispose Callback invoked when the store is disposed
|
|
97
|
+
*/
|
|
98
|
+
initialize(key: string, initialLocation: URI, locationProvider: () => Promise<URI>, onDispose?: () => void): void {
|
|
99
|
+
this._key = key;
|
|
100
|
+
this._location = initialLocation;
|
|
101
|
+
this.locationProvider = locationProvider;
|
|
102
|
+
this.onDisposeCallback = onDispose;
|
|
103
|
+
this.currentWorkspaceRoot = this.getFirstWorkspaceRoot();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@postConstruct()
|
|
107
|
+
protected init(): void {
|
|
108
|
+
this.toDispose.push(this.onDidChangeLocationEmitter);
|
|
109
|
+
this.toDispose.push(
|
|
110
|
+
this.workspaceService.onWorkspaceChanged(() => this.handleWorkspaceChange())
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
protected async handleWorkspaceChange(): Promise<void> {
|
|
115
|
+
const newWorkspaceRoot = this.getFirstWorkspaceRoot();
|
|
116
|
+
|
|
117
|
+
// Check if the first workspace root actually changed
|
|
118
|
+
if (this.currentWorkspaceRoot?.toString() !== newWorkspaceRoot?.toString()) {
|
|
119
|
+
this.currentWorkspaceRoot = newWorkspaceRoot;
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const newLocation = await this.locationProvider();
|
|
123
|
+
if (this._location.toString() !== newLocation.toString()) {
|
|
124
|
+
this._location = newLocation;
|
|
125
|
+
this.onDidChangeLocationEmitter.fire(newLocation);
|
|
126
|
+
this.logger.debug(`Metadata store location changed for key '${this._key}'`, {
|
|
127
|
+
newLocation: newLocation.toString()
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.logger.error(`Failed to update location for metadata store '${this._key}'`, error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
protected getFirstWorkspaceRoot(): URI | undefined {
|
|
137
|
+
const roots = this.workspaceService.tryGetRoots();
|
|
138
|
+
return roots.length > 0 ? roots[0].resource : undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async ensureExists(): Promise<void> {
|
|
142
|
+
try {
|
|
143
|
+
await this.fileService.createFolder(this._location);
|
|
144
|
+
this.logger.debug(`Ensured metadata store exists for key '${this._key}'`, {
|
|
145
|
+
location: this._location.toString()
|
|
146
|
+
});
|
|
147
|
+
} catch (error) {
|
|
148
|
+
this.logger.error(`Failed to create metadata store directory for key '${this._key}'`, error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async delete(): Promise<void> {
|
|
154
|
+
try {
|
|
155
|
+
const exists = await this.fileService.exists(this._location);
|
|
156
|
+
if (exists) {
|
|
157
|
+
await this.fileService.delete(this._location, { recursive: true, useTrash: false });
|
|
158
|
+
this.logger.debug(`Deleted metadata store for key '${this._key}'`, {
|
|
159
|
+
location: this._location.toString()
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.logger.error(`Failed to delete metadata store directory for key '${this._key}'`, error);
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
dispose(): void {
|
|
169
|
+
this.toDispose.dispose();
|
|
170
|
+
this.onDisposeCallback?.();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -57,6 +57,8 @@ import { WorkspaceUserWorkingDirectoryProvider } from './workspace-user-working-
|
|
|
57
57
|
import { WindowTitleUpdater } from '@theia/core/lib/browser/window/window-title-updater';
|
|
58
58
|
import { WorkspaceWindowTitleUpdater } from './workspace-window-title-updater';
|
|
59
59
|
import { CanonicalUriService } from './canonical-uri-service';
|
|
60
|
+
import { WorkspaceMetadataStorageService, WorkspaceMetadataStorageServiceImpl, WorkspaceMetadataStoreFactory } from './metadata-storage';
|
|
61
|
+
import { WorkspaceMetadataStoreImpl } from './metadata-storage/workspace-metadata-store';
|
|
60
62
|
|
|
61
63
|
export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
|
|
62
64
|
bindWorkspacePreferences(bind);
|
|
@@ -101,6 +103,11 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
|
|
|
101
103
|
bind(WorkspaceStorageService).toSelf().inSingletonScope();
|
|
102
104
|
rebind(StorageService).toService(WorkspaceStorageService);
|
|
103
105
|
|
|
106
|
+
bind(WorkspaceMetadataStoreImpl).toSelf();
|
|
107
|
+
bind(WorkspaceMetadataStoreFactory).toFactory(ctx => () => ctx.container.get(WorkspaceMetadataStoreImpl));
|
|
108
|
+
bind(WorkspaceMetadataStorageServiceImpl).toSelf().inSingletonScope();
|
|
109
|
+
bind(WorkspaceMetadataStorageService).toService(WorkspaceMetadataStorageServiceImpl);
|
|
110
|
+
|
|
104
111
|
bind(LabelProviderContribution).to(WorkspaceUriLabelProviderContribution).inSingletonScope();
|
|
105
112
|
bind(WorkspaceVariableContribution).toSelf().inSingletonScope();
|
|
106
113
|
bind(VariableContribution).toService(WorkspaceVariableContribution);
|
|
@@ -394,12 +394,11 @@ export class WorkspaceTrustService {
|
|
|
394
394
|
this.storage.setData(STORAGE_TRUSTED, undefined);
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
-
if (change.preferenceName === WORKSPACE_TRUST_ENABLED && this.isWorkspaceTrustResolved() && await this.confirmRestart()) {
|
|
398
|
-
this.windowService.setSafeToShutDown();
|
|
399
|
-
this.windowService.reload();
|
|
400
|
-
}
|
|
401
|
-
|
|
402
397
|
if (change.preferenceName === WORKSPACE_TRUST_ENABLED) {
|
|
398
|
+
if (!await this.isEmptyWorkspace() && this.isWorkspaceTrustResolved() && await this.confirmRestart()) {
|
|
399
|
+
this.windowService.setSafeToShutDown();
|
|
400
|
+
this.windowService.reload();
|
|
401
|
+
}
|
|
403
402
|
this.resolveWorkspaceTrust();
|
|
404
403
|
}
|
|
405
404
|
|