Skip to content

Commit

Permalink
Added poc for in-memory COMMIT_MESSAGE file editor handling
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnnyCrazy committed Jul 27, 2020
1 parent e000928 commit f18ba9a
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 11 deletions.
2 changes: 2 additions & 0 deletions extensions/git/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1892,6 +1892,7 @@
"file-type": "^7.2.0",
"iconv-lite-umd": "0.6.8",
"jschardet": "2.2.1",
"uuid": "^8.2.0",
"vscode-extension-telemetry": "0.1.1",
"vscode-nls": "^4.0.0",
"vscode-uri": "^2.0.0",
Expand All @@ -1902,6 +1903,7 @@
"@types/file-type": "^5.2.1",
"@types/mocha": "2.2.43",
"@types/node": "^12.12.31",
"@types/uuid": "^8.0.0",
"@types/which": "^1.0.28",
"mocha": "^3.2.0",
"mocha-junit-reporter": "^1.23.3",
Expand Down
87 changes: 87 additions & 0 deletions extensions/git/src/commitFileSystemProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { FileSystemProvider, FileChangeEvent, EventEmitter, Event, Disposable, FileStat, Uri, FileType, workspace, FileSystemError } from 'vscode';
import { EmptyDisposable } from './util';
import { promises as fs } from 'fs';

export class GitCommitFileSystemProvider implements FileSystemProvider {
private _onDidChangeFile = new EventEmitter<FileChangeEvent[]>();
readonly onDidChangeFile: Event<FileChangeEvent[]> = this._onDidChangeFile.event;

private disposables: Disposable[] = [];

private fileCache: Record<string, Uint8Array> = {};

constructor() {
this.disposables.push(
workspace.registerFileSystemProvider('gitcommit', this, { isReadonly: false, isCaseSensitive: true }),
workspace.registerResourceLabelFormatter({
scheme: 'gitcommit',
formatting: {
label: '${authority} (gitcommit)',
separator: '/'
}
})
);
}

async stat(uri: Uri): Promise<FileStat> {
// TODO: Should we do error handling here? If so, we may need sth like toFileSystemProviderErrorCode
if (this.fileCache[uri.authority]) {
return { type: FileType.File, ctime: 0, mtime: 0, size: this.fileCache[uri.authority].length };
}

const { size } = await fs.stat(uri.fsPath);
return { ctime: 0, mtime: 0, size, type: FileType.File };
}

readDirectory(): Thenable<[string, FileType][]> {
throw new Error('Method not implemented.');
}

createDirectory(): void {
throw new Error('Method not implemented.');
}

async readFile(uri: Uri): Promise<Uint8Array> {
// TODO: Should we do more error handling here? If so, we may need sth like toFileSystemProviderErrorCode
if (!this.fileCache[uri.authority]) {
try {
this.fileCache[uri.authority] = await fs.readFile(uri.fsPath);
} catch (error) {
// TODO ingore for now, maybe go for toFileSystemProviderErrorCode
}
}
return this.fileCache[uri.authority];
}

async writeFile(uri: Uri, content: Uint8Array): Promise<void> {
if (this.fileCache[uri.authority]) {
this.fileCache[uri.authority] = content;
} else {
throw FileSystemError.FileNotFound();
}
}

delete(uri: Uri): void {
if (this.fileCache[uri.authority]) {
delete this.fileCache[uri.authority];
} else {
throw FileSystemError.FileNotFound();
}
}

rename(): void {
throw new Error('Method not implemented.');
}

dispose(): void {
this.disposables.forEach(d => d.dispose());
}

watch(): Disposable {
return EmptyDisposable;
}
}
24 changes: 13 additions & 11 deletions extensions/git/src/gitEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import { workspace, window, Uri, Position, Selection } from 'vscode';
import { workspace, window, Uri } from 'vscode';
import { v4 as uuid } from 'uuid';


import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
import { IDisposable, EmptyDisposable } from './util';
Expand All @@ -24,19 +26,19 @@ export class GitEditor implements IIPCHandler {

async handle({ commitMessagePath }: GitEditorRequest): Promise<any> {
if (commitMessagePath) {
const file = Uri.file(commitMessagePath);
const doc = await workspace.openTextDocument(file);
const editor = await window.showTextDocument(doc);

// We don't want to remember the cursor position.
// One should be able to start writing the message immediately.
const position = new Position(0, 0);
editor.selection = new Selection(position, position);
const id = uuid();
const uri = Uri.parse(`gitcommit://${id}/${commitMessagePath}`);
const doc = await workspace.openTextDocument(uri);
await window.showTextDocument(doc);

return new Promise((c) => {
const onDidChange = window.onDidChangeVisibleTextEditors((editors) => {
if (editors.indexOf(editor) < 0) {
const onDidChange = window.onDidChangeVisibleTextEditors(async (editors) => {
if (!editors.find(editor => `${editor.document.uri}` === `${uri}`)) {
onDidChange.dispose();

// dump in-memory content to actual COMMIT_MESSAGE file
await workspace.fs.writeFile(Uri.file(commitMessagePath), await workspace.fs.readFile(uri));
await workspace.fs.delete(uri);
return c(true);
}
});
Expand Down
2 changes: 2 additions & 0 deletions extensions/git/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { GitTimelineProvider } from './timelineProvider';
import { registerAPICommands } from './api/api1';
import { TerminalEnvironmentManager } from './terminal';
import { createIPCServer, IIPCServer } from './ipc/ipcServer';
import { GitCommitFileSystemProvider } from './commitFileSystemProvider';

const deactivateTasks: { (): Promise<any>; }[] = [];

Expand Down Expand Up @@ -82,6 +83,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
disposables.push(
new CommandCenter(git, model, outputChannel, telemetryReporter),
new GitFileSystemProvider(model),
new GitCommitFileSystemProvider(),
new GitDecorations(model),
new GitProtocolHandler(),
new GitTimelineProvider(model)
Expand Down
10 changes: 10 additions & 0 deletions extensions/git/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.31.tgz#d6b4f9645fee17f11319b508fb1001797425da51"
integrity sha512-T+wnJno8uh27G9c+1T+a1/WYCHzLeDqtsGJkoEdSp2X8RTh3oOCZQcUnjAx90CS8cmmADX51O0FI/tu9s0yssg==

"@types/uuid@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0"
integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw==

"@types/which@^1.0.28":
version "1.0.28"
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
Expand Down Expand Up @@ -850,6 +855,11 @@ uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==

uuid@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e"
integrity sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==

[email protected]:
version "1.10.0"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
Expand Down

0 comments on commit f18ba9a

Please sign in to comment.