Save: Flush to disk after writing to file (fixes #9589)
This commit is contained in:
parent
6dd65cc0c5
commit
974bce453e
8
src/typings/node.d.ts
vendored
8
src/typings/node.d.ts
vendored
|
@ -1442,6 +1442,8 @@ declare module "fs" {
|
|||
export function futimesSync(fd: number, atime: Date, mtime: Date): void;
|
||||
export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function fsyncSync(fd: number): void;
|
||||
export function fdatasync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function fdatasyncSync(fd: number): void;
|
||||
export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void;
|
||||
export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void;
|
||||
export function write(fd: number, data: any, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void;
|
||||
|
@ -1503,9 +1505,9 @@ declare module "fs" {
|
|||
* @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer.
|
||||
*/
|
||||
export function readFileSync(filename: string, options?: { flag?: string; }): Buffer;
|
||||
export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string|number, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string|number, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string|number, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void;
|
||||
export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void;
|
||||
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
|
|
|
@ -312,4 +312,36 @@ export function mv(source: string, target: string, callback: (error: Error) => v
|
|||
|
||||
return callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
// Calls fs.writeFile() followed by a fs.sync() call to flush the changes to disk
|
||||
// We do this in cases where we want to make sure the data is really on disk and
|
||||
// not in some cache.
|
||||
//
|
||||
// See https://github.com/nodejs/node/blob/v5.10.0/lib/fs.js#L1194
|
||||
export function writeFileAndFlush(path: string, data: string | NodeBuffer, options: { encoding?: string; mode?: number; flag?: string; }, callback: (error: Error) => void): void {
|
||||
if (!options) {
|
||||
options = { encoding: 'utf8', mode: 0o666, flag: 'w' };
|
||||
} else if (typeof options === 'string') {
|
||||
options = { encoding: <string>options, mode: 0o666, flag: 'w' };
|
||||
}
|
||||
|
||||
// Open the file with same flags and mode as fs.writeFile()
|
||||
fs.open(path, options.flag, options.mode, (openError, fd) => {
|
||||
if (openError) {
|
||||
return callback(openError);
|
||||
}
|
||||
|
||||
// It is valid to pass a fd handle to fs.writeFile() and this will keep the handle open!
|
||||
fs.writeFile(fd, data, options.encoding, (writeError) => {
|
||||
if (writeError) {
|
||||
return fs.close(fd, () => callback(writeError)); // still need to close the handle on error!
|
||||
}
|
||||
|
||||
// Flush contents (not metadata) of the file to disk
|
||||
fs.fdatasync(fd, (syncError) => {
|
||||
return fs.close(fd, (closeError) => callback(syncError || closeError)); // make sure to carry over the fdatasync error if any!
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -135,6 +135,12 @@ export function writeFile(path: string, data: any, encoding: string = 'utf8'): P
|
|||
return nfcall(fs.writeFile, path, data, encoding);
|
||||
}
|
||||
|
||||
export function writeFileAndFlush(path: string, data: string, encoding?: string): Promise;
|
||||
export function writeFileAndFlush(path: string, data: NodeBuffer, encoding?: string): Promise;
|
||||
export function writeFileAndFlush(path: string, data: any, encoding: string = 'utf8'): Promise {
|
||||
return nfcall(extfs.writeFileAndFlush, path, data, encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a dir and return only subfolders
|
||||
*/
|
||||
|
|
|
@ -18,9 +18,9 @@ import extfs = require('vs/base/node/extfs');
|
|||
suite('Extfs', () => {
|
||||
|
||||
test('mkdirp', function (done: () => void) {
|
||||
var id = uuid.generateUuid();
|
||||
var parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
var newDir = path.join(parentDir, 'extfs', id);
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
const newDir = path.join(parentDir, 'extfs', id);
|
||||
|
||||
extfs.mkdirp(newDir, 493, (error) => {
|
||||
assert.ok(!error);
|
||||
|
@ -31,12 +31,12 @@ suite('Extfs', () => {
|
|||
});
|
||||
|
||||
test('copy, move and delete', function (done: () => void) {
|
||||
var id = uuid.generateUuid();
|
||||
var id2 = uuid.generateUuid();
|
||||
var sourceDir = require.toUrl('./fixtures');
|
||||
var parentDir = path.join(os.tmpdir(), 'vsctests', 'extfs');
|
||||
var targetDir = path.join(parentDir, id);
|
||||
var targetDir2 = path.join(parentDir, id2);
|
||||
const id = uuid.generateUuid();
|
||||
const id2 = uuid.generateUuid();
|
||||
const sourceDir = require.toUrl('./fixtures');
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', 'extfs');
|
||||
const targetDir = path.join(parentDir, id);
|
||||
const targetDir2 = path.join(parentDir, id2);
|
||||
|
||||
extfs.copy(sourceDir, targetDir, (error) => {
|
||||
assert.ok(!error);
|
||||
|
@ -76,9 +76,9 @@ suite('Extfs', () => {
|
|||
|
||||
test('readdir', function (done: () => void) {
|
||||
if (strings.canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) {
|
||||
var id = uuid.generateUuid();
|
||||
var parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
var newDir = path.join(parentDir, 'extfs', id, 'öäü');
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
const newDir = path.join(parentDir, 'extfs', id, 'öäü');
|
||||
|
||||
extfs.mkdirp(newDir, 493, (error) => {
|
||||
assert.ok(!error);
|
||||
|
@ -94,4 +94,30 @@ suite('Extfs', () => {
|
|||
done();
|
||||
}
|
||||
});
|
||||
|
||||
test('writeFileAndFlush', function (done: () => void) {
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
const newDir = path.join(parentDir, 'extfs', id);
|
||||
const testFile = path.join(newDir, 'flushed.txt');
|
||||
|
||||
extfs.mkdirp(newDir, 493, (error) => {
|
||||
assert.ok(!error);
|
||||
assert.ok(fs.existsSync(newDir));
|
||||
|
||||
extfs.writeFileAndFlush(testFile, 'Hello World', null, (error) => {
|
||||
assert.ok(!error);
|
||||
assert.equal(fs.readFileSync(testFile), 'Hello World');
|
||||
|
||||
const largeString = (new Array(100 * 1024)).join('Large String\n');
|
||||
|
||||
extfs.writeFileAndFlush(testFile, largeString, null, (error) => {
|
||||
assert.ok(!error);
|
||||
assert.equal(fs.readFileSync(testFile), largeString);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -272,13 +272,13 @@ export class FileService implements IFileService {
|
|||
|
||||
// Write fast if we do UTF 8 without BOM
|
||||
if (!addBom && encodingToWrite === encoding.UTF8) {
|
||||
writeFilePromise = pfs.writeFile(absolutePath, value, encoding.UTF8);
|
||||
writeFilePromise = pfs.writeFileAndFlush(absolutePath, value, encoding.UTF8);
|
||||
}
|
||||
|
||||
// Otherwise use encoding lib
|
||||
else {
|
||||
let encoded = encoding.encode(value, encodingToWrite, { addBOM: addBom });
|
||||
writeFilePromise = pfs.writeFile(absolutePath, encoded);
|
||||
writeFilePromise = pfs.writeFileAndFlush(absolutePath, encoded);
|
||||
}
|
||||
|
||||
// 4.) set contents
|
||||
|
|
Loading…
Reference in a new issue