Skip to content

Commit 818d499

Browse files
committed
initial notebook save on remote eh
1 parent 675314d commit 818d499

File tree

9 files changed

+105
-4
lines changed

9 files changed

+105
-4
lines changed

src/vs/workbench/api/browser/mainThreadNotebook.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
7272
extensionId: extension.id.value,
7373
});
7474
return result;
75-
}
75+
},
76+
save: (uri, versionId, options, token) => {
77+
return this._proxy.$saveNotebook(handle, uri, versionId, options, token);
78+
},
7679
}));
7780

7881
if (data) {

src/vs/workbench/api/common/extHost.api.impl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
170170
const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
171171
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
172172
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadBulkEdits)));
173-
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments));
173+
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments, extHostConsumerFileSystem));
174174
const extHostNotebookDocuments = rpcProtocol.set(ExtHostContext.ExtHostNotebookDocuments, new ExtHostNotebookDocuments(extHostNotebook));
175175
const extHostNotebookEditors = rpcProtocol.set(ExtHostContext.ExtHostNotebookEditors, new ExtHostNotebookEditors(extHostLogService, extHostNotebook));
176176
const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook, extHostCommands, extHostLogService));

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,6 +2280,7 @@ export interface ExtHostNotebookShape extends ExtHostNotebookDocumentsAndEditors
22802280

22812281
$dataToNotebook(handle: number, data: VSBuffer, token: CancellationToken): Promise<SerializableObjectWithBuffers<NotebookDataDto>>;
22822282
$notebookToData(handle: number, data: SerializableObjectWithBuffers<NotebookDataDto>, token: CancellationToken): Promise<VSBuffer>;
2283+
$saveNotebook(handle: number, uri: UriComponents, versionId: number, options: files.IWriteFileOptions, token: CancellationToken): Promise<files.IStat>;
22832284
}
22842285

22852286
export interface ExtHostNotebookDocumentSaveParticipantShape {

src/vs/workbench/api/common/extHostNotebook.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { isFalsyOrWhitespace } from 'vs/base/common/strings';
1414
import { assertIsDefined } from 'vs/base/common/types';
1515
import { URI, UriComponents } from 'vs/base/common/uri';
1616
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
17+
import * as files from 'vs/platform/files/common/files';
1718
import { Cache } from 'vs/workbench/api/common/cache';
1819
import { ExtHostNotebookShape, IMainContext, IModelAddedData, INotebookCellStatusBarListDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookEditorAddData, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookEditorsShape, MainThreadNotebookShape, NotebookDataDto } from 'vs/workbench/api/common/extHost.protocol';
1920
import { ApiCommand, ApiCommandArgument, ApiCommandResult, CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
@@ -27,6 +28,9 @@ import type * as vscode from 'vscode';
2728
import { ExtHostCell, ExtHostNotebookDocument } from './extHostNotebookDocument';
2829
import { ExtHostNotebookEditor } from './extHostNotebookEditor';
2930
import { onUnexpectedExternalError } from 'vs/base/common/errors';
31+
import { IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
32+
// import { filter } from 'vs/base/common/objects';
33+
// import { ExtHostFileSystem } from 'vs/workbench/api/common/extHostFileSystem';
3034

3135

3236

@@ -69,6 +73,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
6973
commands: ExtHostCommands,
7074
private _textDocumentsAndEditors: ExtHostDocumentsAndEditors,
7175
private _textDocuments: ExtHostDocuments,
76+
private _extHostFileSystem: IExtHostConsumerFileSystem
7277
) {
7378
this._notebookProxy = mainContext.getProxy(MainContext.MainThreadNotebook);
7479
this._notebookDocumentsProxy = mainContext.getProxy(MainContext.MainThreadNotebookDocuments);
@@ -301,6 +306,50 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
301306
return VSBuffer.wrap(bytes);
302307
}
303308

309+
async $saveNotebook(handle: number, uriComponents: UriComponents, versionId: number, options: files.IWriteFileOptions, token: CancellationToken): Promise<files.IStat> {
310+
const uri = URI.revive(uriComponents);
311+
const serializer = this._notebookSerializer.get(handle);
312+
if (!serializer) {
313+
throw new Error('NO serializer found');
314+
}
315+
316+
const document = this._documents.get(uri);
317+
if (!document) {
318+
throw new Error('Document NOT found');
319+
}
320+
321+
if (document.versionId !== versionId) {
322+
throw new Error('Document version mismatch');
323+
}
324+
325+
const data: vscode.NotebookData = {
326+
metadata: document.apiNotebook.metadata, // filter(document.apiNotebook.metadata, key => !serializer.options.transientDocumentMetadata[key]),
327+
cells: [],
328+
};
329+
330+
for (const cell of document.apiNotebook.getCells()) {
331+
const cellData = new extHostTypes.NotebookCellData(
332+
cell.kind,
333+
cell.document.getText(),
334+
cell.document.languageId,
335+
cell.mime,
336+
[...cell.outputs],
337+
cell.metadata,
338+
cell.executionSummary
339+
);
340+
341+
// cellData.outputs = !serializer.options.transientOutputs ? cell.outputs : [];
342+
// cellData.metadata = filter(cell.metadata, key => !serializer.options.transientCellMetadata[key]);
343+
344+
data.cells.push(cellData);
345+
}
346+
347+
const bytes = await serializer.serializeNotebook(data, token);
348+
await this._extHostFileSystem.value.writeFile(uri, bytes);
349+
350+
const stats = await this._extHostFileSystem.value.stat(uri);
351+
return stats;
352+
}
304353
// --- open, save, saveAs, backup
305354

306355

src/vs/workbench/api/common/extHostNotebookDocument.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ export class ExtHostNotebookDocument {
186186
this._disposed = true;
187187
}
188188

189+
get versionId(): number {
190+
return this._versionId;
191+
}
192+
189193
get apiNotebook(): vscode.NotebookDocument {
190194
if (!this._notebook) {
191195
const that = this;

src/vs/workbench/api/test/browser/extHostNotebook.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNoteboo
2424
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
2525
import { VSBuffer } from 'vs/base/common/buffer';
2626
import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
27+
import { ExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
28+
import { ExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
2729

2830
suite('NotebookCell#Document', function () {
2931

@@ -34,6 +36,7 @@ suite('NotebookCell#Document', function () {
3436
let extHostDocuments: ExtHostDocuments;
3537
let extHostNotebooks: ExtHostNotebookController;
3638
let extHostNotebookDocuments: ExtHostNotebookDocuments;
39+
let extHostConsumerFileSystem: ExtHostConsumerFileSystem;
3740

3841
const notebookUri = URI.parse('test:///notebook.file');
3942
const disposables = new DisposableStore();
@@ -53,11 +56,12 @@ suite('NotebookCell#Document', function () {
5356
});
5457
extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(rpcProtocol, new NullLogService());
5558
extHostDocuments = new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors);
59+
extHostConsumerFileSystem = new ExtHostConsumerFileSystem(rpcProtocol, new ExtHostFileSystemInfo());
5660
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, new ExtHostCommands(rpcProtocol, new NullLogService(), new class extends mock<IExtHostTelemetry>() {
5761
override onExtensionError(): boolean {
5862
return true;
5963
}
60-
}), extHostDocumentsAndEditors, extHostDocuments);
64+
}), extHostDocumentsAndEditors, extHostDocuments, extHostConsumerFileSystem);
6165
extHostNotebookDocuments = new ExtHostNotebookDocuments(extHostNotebooks);
6266

6367
const reg = extHostNotebooks.registerNotebookSerializer(nullExtensionDescription, 'test', new class extends mock<vscode.NotebookSerializer>() { });

src/vs/workbench/api/test/browser/extHostNotebookKernel.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/
2626
import { TestRPCProtocol } from 'vs/workbench/api/test/common/testRPCProtocol';
2727
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
2828
import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
29+
import { ExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
30+
import { ExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
2931

3032
suite('NotebookKernel', function () {
3133

@@ -37,6 +39,7 @@ suite('NotebookKernel', function () {
3739
let extHostNotebooks: ExtHostNotebookController;
3840
let extHostNotebookDocuments: ExtHostNotebookDocuments;
3941
let extHostCommands: ExtHostCommands;
42+
let extHostConsumerFileSystem: ExtHostConsumerFileSystem;
4043

4144
const notebookUri = URI.parse('test:///notebook.file');
4245
const kernelData = new Map<number, INotebookKernelDto2>();
@@ -94,7 +97,8 @@ suite('NotebookKernel', function () {
9497
return true;
9598
}
9699
});
97-
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments);
100+
extHostConsumerFileSystem = new ExtHostConsumerFileSystem(rpcProtocol, new ExtHostFileSystemInfo());
101+
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments, extHostConsumerFileSystem);
98102

99103
extHostNotebookDocuments = new ExtHostNotebookDocuments(extHostNotebooks);
100104

src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import { IMarkdownString } from 'vs/base/common/htmlContent';
1111
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
1212
import { Schemas } from 'vs/base/common/network';
1313
import { filter } from 'vs/base/common/objects';
14+
import { basename } from 'vs/base/common/resources';
1415
import { assertType } from 'vs/base/common/types';
1516
import { URI } from 'vs/base/common/uri';
17+
import { IWriteFileOptions, IFileStatWithMetadata, FileType, FilePermission, etag } from 'vs/platform/files/common/files';
1618
import { IRevertOptions, ISaveOptions, IUntypedEditorInput } from 'vs/workbench/common/editor';
1719
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
1820
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
@@ -252,6 +254,38 @@ export class NotebookFileWorkingCopyModel extends Disposable implements IStoredF
252254
return bufferToStream(bytes);
253255
}
254256

257+
async save(options: IWriteFileOptions, token: CancellationToken): Promise<IFileStatWithMetadata> {
258+
const serializer = await this.getNotebookSerializer();
259+
260+
if (token.isCancellationRequested) {
261+
throw new CancellationError();
262+
}
263+
264+
// const stat = await this.validateWriteFile(provider, resource, options);
265+
// const handle = await provider.open(resource, { create: true, unlock: options?.unlock ?? false });
266+
267+
268+
const stat = await serializer.save(this._notebookModel.uri, this._notebookModel.versionId, options, token);
269+
const fileStat: IFileStatWithMetadata = {
270+
resource: this._notebookModel.uri,
271+
// name: providerExtUri.basename(resource),
272+
name: basename(this._notebookModel.uri),
273+
isFile: (stat.type & FileType.File) !== 0,
274+
isDirectory: (stat.type & FileType.Directory) !== 0,
275+
isSymbolicLink: (stat.type & FileType.SymbolicLink) !== 0,
276+
mtime: stat.mtime,
277+
ctime: stat.ctime,
278+
size: stat.size,
279+
readonly: Boolean((stat.permissions ?? 0) & FilePermission.Readonly), // || Boolean(provider.capabilities & FileSystemProviderCapabilities.Readonly),
280+
// readonly: Boolean((stat.permissions ?? 0) & FilePermission.Readonly) || Boolean(provider.capabilities & FileSystemProviderCapabilities.Readonly),
281+
locked: Boolean((stat.permissions ?? 0) & FilePermission.Locked),
282+
etag: etag({ mtime: stat.mtime, size: stat.size }),
283+
children: undefined
284+
};
285+
286+
return fileStat;
287+
}
288+
255289
async update(stream: VSBufferReadableStream, token: CancellationToken): Promise<void> {
256290
const serializer = await this.getNotebookSerializer();
257291

src/vs/workbench/contrib/notebook/common/notebookService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode
1414
import { IDisposable } from 'vs/base/common/lifecycle';
1515
import { VSBuffer } from 'vs/base/common/buffer';
1616
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
17+
import { IStat, IWriteFileOptions } from 'vs/platform/files/common/files';
1718

1819

1920
export const INotebookService = createDecorator<INotebookService>('notebookService');
@@ -29,6 +30,7 @@ export interface INotebookSerializer {
2930
options: TransientOptions;
3031
dataToNotebook(data: VSBuffer): Promise<NotebookData>;
3132
notebookToData(data: NotebookData): Promise<VSBuffer>;
33+
save(uri: URI, versionId: number, options: IWriteFileOptions, token: CancellationToken): Promise<IStat>;
3234
}
3335

3436
export interface INotebookRawData {

0 commit comments

Comments
 (0)