Skip to content

Commit 1db65b8

Browse files
authored
Ensure that search location is stored as a string (#20106)
For #20104 The Cause: The `workspaceFolder` field is set using an internal field `searchLocation`. `searchLocation` is what gets saved to Memento as `Uri`. when we read it back it looks like this: ![image](https://user-images.githubusercontent.com/3840081/198420406-fb4c9b87-1276-4717-8043-69d95dcdba48.png) Interim Solution: * Reading (broken case): Since there are already existing cases where this is broken. The surgical fix is to read bad value, extract the `scheme` and `path`, use that to re-create the URI. * Reading/Writing (new case): Make sure that we convert Uri to string before writing and parse back the Uri when reading. Long term solution: Object written to memento needs to be serialized using a custom serializer that validates all values before writing and after reading.
1 parent 83fff4f commit 1db65b8

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

src/client/common/persistentState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export class PersistentStateFactory implements IPersistentStateFactory, IExtensi
152152
// a simpler, alternate API
153153
// for components to use
154154

155-
interface IPersistentStorage<T> {
155+
export interface IPersistentStorage<T> {
156156
get(): T;
157157
set(value: T): Promise<void>;
158158
}

src/client/pythonEnvironments/index.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Licensed under the MIT License.
33

44
import * as vscode from 'vscode';
5-
import { getGlobalStorage } from '../common/persistentState';
5+
import { Uri } from 'vscode';
6+
import { getGlobalStorage, IPersistentStorage } from '../common/persistentState';
67
import { getOSType, OSType } from '../common/utils/platform';
78
import { ActivationResult, ExtensionState } from '../components';
89
import { PythonEnvInfo } from './base/info';
@@ -184,11 +185,38 @@ function createWorkspaceLocator(ext: ExtensionState): WorkspaceLocators {
184185
return locators;
185186
}
186187

188+
function getFromStorage(storage: IPersistentStorage<PythonEnvInfo[]>): PythonEnvInfo[] {
189+
return storage.get().map((e) => {
190+
if (e.searchLocation) {
191+
if (typeof e.searchLocation === 'string') {
192+
e.searchLocation = Uri.parse(e.searchLocation);
193+
} else if ('scheme' in e.searchLocation && 'path' in e.searchLocation) {
194+
e.searchLocation = Uri.parse(`${e.searchLocation.scheme}://${e.searchLocation.path}`);
195+
}
196+
}
197+
return e;
198+
});
199+
}
200+
201+
function putIntoStorage(storage: IPersistentStorage<PythonEnvInfo[]>, envs: PythonEnvInfo[]): Promise<void> {
202+
storage.set(
203+
envs.map((e) => {
204+
if (e.searchLocation) {
205+
// Make TS believe it is string. This is temporary. We need to serialize this in
206+
// a custom way.
207+
e.searchLocation = (e.searchLocation.toString() as unknown) as Uri;
208+
}
209+
return e;
210+
}),
211+
);
212+
return Promise.resolve();
213+
}
214+
187215
async function createCollectionCache(ext: ExtensionState): Promise<IEnvsCollectionCache> {
188216
const storage = getGlobalStorage<PythonEnvInfo[]>(ext.context, 'PYTHON_ENV_INFO_CACHE', []);
189217
const cache = await createCache({
190-
get: () => storage.get(),
191-
store: async (e) => storage.set(e),
218+
get: () => getFromStorage(storage),
219+
store: async (e) => putIntoStorage(storage, e),
192220
});
193221
return cache;
194222
}

0 commit comments

Comments
 (0)