提交 5a318c23 编写于 作者: B Benjamin Pasero

perf - remove duplicated mkdirp method

上级 9486025f
......@@ -12,6 +12,8 @@ import * as flow from 'vs/base/node/flow';
import * as fs from 'fs';
import * as paths from 'path';
import { TPromise } from 'vs/base/common/winjs.base';
import { nfcall } from 'vs/base/common/async';
const loop = flow.loop;
......@@ -41,80 +43,72 @@ export function readdir(path: string, callback: (error: Error, files: string[])
return fs.readdir(path, callback);
}
export function mkdirp(path: string, mode: number, callback: (error: Error) => void): void {
fs.exists(path, exists => {
if (exists) {
return isDirectory(path, (err: Error, itIs?: boolean) => {
if (err) {
return callback(err);
}
if (!itIs) {
return callback(new Error('"' + path + '" is not a directory.'));
}
callback(null);
});
}
mkdirp(paths.dirname(path), mode, (err: Error) => {
if (err) { callback(err); return; }
if (mode) {
fs.mkdir(path, mode, error => {
if (error) {
return callback(error);
}
fs.chmod(path, mode, callback); // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104
});
} else {
fs.mkdir(path, null, callback);
}
});
});
}
function isDirectory(path: string, callback: (error: Error, isDirectory?: boolean) => void): void {
fs.stat(path, (error, stat) => {
if (error) { return callback(error); }
callback(null, stat.isDirectory());
});
}
export function copy(source: string, target: string, callback: (error: Error) => void, copiedSources?: { [path: string]: boolean }): void {
if (!copiedSources) {
copiedSources = Object.create(null);
}
fs.stat(source, (error, stat) => {
if (error) { return callback(error); }
if (!stat.isDirectory()) { return pipeFs(source, target, stat.mode & 511, callback); }
if (error) {
return callback(error);
}
if (!stat.isDirectory()) {
return pipeFs(source, target, stat.mode & 511, callback);
}
if (copiedSources[source]) {
return callback(null); // escape when there are cycles (can happen with symlinks)
} else {
copiedSources[source] = true; // remember as copied
}
mkdirp(target, stat.mode & 511, err => {
copiedSources[source] = true; // remember as copied
const proceed = function () {
readdir(source, (err, files) => {
loop(files, (file: string, clb: (error: Error, result: string[]) => void) => {
copy(paths.join(source, file), paths.join(target, file), (error: Error) => clb(error, void 0), copiedSources);
}, callback);
});
};
mkdirp(target, stat.mode & 511).done(proceed, proceed);
});
}
export function mkdirp(path: string, mode?: number): TPromise<boolean> {
const mkdir = () => nfcall(fs.mkdir, path, mode)
.then(null, (err: NodeJS.ErrnoException) => {
if (err.code === 'EEXIST') {
return nfcall(fs.stat, path)
.then((stat: fs.Stats) => stat.isDirectory
? null
: TPromise.wrapError(new Error(`'${path}' exists and is not a directory.`)));
}
return TPromise.wrapError<boolean>(err);
});
// is root?
if (path === paths.dirname(path)) {
return TPromise.as(true);
}
return mkdir().then(null, (err: NodeJS.ErrnoException) => {
if (err.code === 'ENOENT') {
return mkdirp(paths.dirname(path), mode).then(mkdir);
}
return TPromise.wrapError<boolean>(err);
});
}
function pipeFs(source: string, target: string, mode: number, callback: (error: Error) => void): void {
let callbackHandled = false;
let readStream = fs.createReadStream(source);
let writeStream = fs.createWriteStream(target, { mode: mode });
const readStream = fs.createReadStream(source);
const writeStream = fs.createWriteStream(target, { mode: mode });
let onError = (error: Error) => {
const onError = (error: Error) => {
if (!callbackHandled) {
callbackHandled = true;
callback(error);
......@@ -163,7 +157,7 @@ export function del(path: string, tmpFolder: string, callback: (error: Error) =>
return rmRecursive(path, callback);
}
let pathInTemp = paths.join(tmpFolder, uuid.generateUuid());
const pathInTemp = paths.join(tmpFolder, uuid.generateUuid());
fs.rename(path, pathInTemp, (error: Error) => {
if (error) {
return rmRecursive(path, callback); // if rename fails, delete without tmp dir
......@@ -200,7 +194,7 @@ function rmRecursive(path: string, callback: (error: Error) => void): void {
if (err || !stat) {
callback(err);
} else if (!stat.isDirectory() || stat.isSymbolicLink() /* !!! never recurse into links when deleting !!! */) {
let mode = stat.mode;
const mode = stat.mode;
if (!(mode & 128)) { // 128 === 0200
fs.chmod(path, mode | 128, (err: Error) => { // 128 === 0200
if (err) {
......
......@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import * as extfs from 'vs/base/node/extfs';
import { dirname, join } from 'path';
import { join } from 'path';
import { nfcall, Queue } from 'vs/base/common/async';
import * as fs from 'fs';
import * as os from 'os';
......@@ -26,32 +26,7 @@ export function chmod(path: string, mode: number): TPromise<boolean> {
return nfcall(fs.chmod, path, mode);
}
export function mkdirp(path: string, mode?: number): TPromise<boolean> {
const mkdir = () => nfcall(fs.mkdir, path, mode)
.then(null, (err: NodeJS.ErrnoException) => {
if (err.code === 'EEXIST') {
return nfcall(fs.stat, path)
.then((stat: fs.Stats) => stat.isDirectory
? null
: TPromise.wrapError(new Error(`'${path}' exists and is not a directory.`)));
}
return TPromise.wrapError<boolean>(err);
});
// is root?
if (path === dirname(path)) {
return TPromise.as(true);
}
return mkdir().then(null, (err: NodeJS.ErrnoException) => {
if (err.code === 'ENOENT') {
return mkdirp(dirname(path), mode).then(mkdir);
}
return TPromise.wrapError<boolean>(err);
});
}
export import mkdirp = extfs.mkdirp;
export function rimraf(path: string): TPromise<void> {
return lstat(path).then(stat => {
......
......@@ -14,6 +14,7 @@ import extfs = require('vs/base/node/extfs');
import uuid = require('vs/base/common/uuid');
import { ConfigWatcher } from 'vs/base/node/config';
import { onError } from 'vs/base/test/common/utils';
import { mkdirp } from 'vs/base/node/pfs';
suite('Config', () => {
......@@ -23,9 +24,9 @@ suite('Config', () => {
const newDir = path.join(parentDir, 'config', id);
const testFile = path.join(newDir, 'config.json');
extfs.mkdirp(newDir, 493, error => {
callback(error, testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback));
});
const onMkdirp = error => callback(error, testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback));
mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
}
test('defaults', function () {
......
......@@ -18,6 +18,10 @@ import { onError } from 'vs/base/test/common/utils';
const ignore = () => { };
const mkdirp = (path: string, mode: number, callback: (error) => void) => {
extfs.mkdirp(path, mode).done(() => callback(null), error => callback(error));
};
suite('Extfs', () => {
test('mkdirp', function (done: () => void) {
......@@ -25,7 +29,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
......@@ -51,7 +55,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
......@@ -71,7 +75,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
......@@ -97,7 +101,7 @@ suite('Extfs', () => {
const targetDir = path.join(parentDir, id);
const targetDir2 = path.join(parentDir, id2);
extfs.copy(sourceDir, targetDir, (error) => {
extfs.copy(sourceDir, targetDir, error => {
if (error) {
return onError(error, done);
}
......@@ -109,7 +113,7 @@ suite('Extfs', () => {
assert.ok(fs.statSync(path.join(targetDir, 'examples')).isDirectory());
assert.ok(fs.existsSync(path.join(targetDir, 'examples', 'small.jxs')));
extfs.mv(targetDir, targetDir2, (error) => {
extfs.mv(targetDir, targetDir2, error => {
if (error) {
return onError(error, done);
}
......@@ -122,7 +126,7 @@ suite('Extfs', () => {
assert.ok(fs.statSync(path.join(targetDir2, 'examples')).isDirectory());
assert.ok(fs.existsSync(path.join(targetDir2, 'examples', 'small.jxs')));
extfs.mv(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html'), (error) => {
extfs.mv(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html'), error => {
if (error) {
return onError(error, done);
}
......@@ -130,11 +134,11 @@ suite('Extfs', () => {
assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html')));
extfs.del(parentDir, os.tmpdir(), (error) => {
extfs.del(parentDir, os.tmpdir(), error => {
if (error) {
return onError(error, done);
}
}, (error) => {
}, error => {
if (error) {
return onError(error, done);
}
......@@ -152,7 +156,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id, 'öäü');
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
......@@ -176,14 +180,14 @@ suite('Extfs', () => {
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
if (error) {
return onError(error, done);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, 'Hello World', null, (error) => {
extfs.writeFileAndFlush(testFile, 'Hello World', null, error => {
if (error) {
return onError(error, done);
}
......@@ -192,7 +196,7 @@ suite('Extfs', () => {
const largeString = (new Array(100 * 1024)).join('Large String\n');
extfs.writeFileAndFlush(testFile, largeString, null, (error) => {
extfs.writeFileAndFlush(testFile, largeString, null, error => {
if (error) {
return onError(error, done);
}
......@@ -210,7 +214,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
// assume case insensitive file system
if (process.platform === 'win32' || process.platform === 'darwin') {
......@@ -239,7 +243,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
extfs.realpath(newDir, (error, realpath) => {
assert.ok(realpath);
......@@ -255,7 +259,7 @@ suite('Extfs', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
mkdirp(newDir, 493, error => {
let realpath: string;
try {
realpath = extfs.realpathSync(newDir);
......
......@@ -25,7 +25,7 @@ suite('PFS', () => {
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'writefile.txt');
extfs.mkdirp(newDir, 493, (error) => {
const onMkdirp = error => {
if (error) {
return onError(error, done);
}
......@@ -37,7 +37,9 @@ suite('PFS', () => {
extfs.del(parentDir, os.tmpdir(), () => { }, done);
}, error => onError(error, done));
});
};
pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
});
test('writeFile - parallel write on different files works', function (done: () => void) {
......@@ -50,7 +52,7 @@ suite('PFS', () => {
const testFile4 = path.join(newDir, 'writefile4.txt');
const testFile5 = path.join(newDir, 'writefile5.txt');
extfs.mkdirp(newDir, 493, (error) => {
const onMkdirp = error => {
if (error) {
return onError(error, done);
}
......@@ -72,7 +74,9 @@ suite('PFS', () => {
extfs.del(parentDir, os.tmpdir(), () => { }, done);
}, error => onError(error, done));
});
};
pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
});
test('writeFile - parallel write on same files works and is sequentalized', function (done: () => void) {
......@@ -81,7 +85,7 @@ suite('PFS', () => {
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'writefile.txt');
extfs.mkdirp(newDir, 493, (error) => {
const onMkdirp = error => {
if (error) {
return onError(error, done);
}
......@@ -99,7 +103,9 @@ suite('PFS', () => {
extfs.del(parentDir, os.tmpdir(), () => { }, done);
}, error => onError(error, done));
});
};
pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
});
test('rimraf - simple', function (done: () => void) {
......@@ -107,7 +113,7 @@ suite('PFS', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
const onMkdirp = error => {
if (error) {
return onError(error, done);
}
......@@ -119,7 +125,9 @@ suite('PFS', () => {
assert.ok(!fs.existsSync(newDir));
done();
}, error => onError(error, done));
}); // 493 = 0755
};
pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
});
test('rimraf - recursive folder structure', function (done: () => void) {
......@@ -127,7 +135,7 @@ suite('PFS', () => {
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.mkdirp(newDir, 493, (error) => {
const onMkdirp = error => {
if (error) {
return onError(error, done);
}
......@@ -142,6 +150,8 @@ suite('PFS', () => {
assert.ok(!fs.existsSync(newDir));
done();
}, error => onError(error, done));
}); // 493 = 0755
};
pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
});
});
\ No newline at end of file
......@@ -18,6 +18,7 @@ import { EnvironmentService } from 'vs/platform/environment/node/environmentServ
import extfs = require('vs/base/node/extfs');
import uuid = require('vs/base/common/uuid');
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { mkdirp } from 'vs/base/node/pfs';
class SettingsTestEnvironmentService extends EnvironmentService {
......@@ -36,9 +37,9 @@ suite('ConfigurationService - Node', () => {
const newDir = path.join(parentDir, 'config', id);
const testFile = path.join(newDir, 'config.json');
extfs.mkdirp(newDir, 493, (error) => {
callback(testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback));
});
const onMkdirp = error => callback(testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback));
mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error));
}
test('simple', (done: () => void) => {
......
......@@ -11,7 +11,6 @@ import { checksum } from 'vs/base/node/crypto';
import { EventEmitter } from 'events';
import { tmpdir } from 'os';
import { spawn } from 'child_process';
import { mkdirp } from 'vs/base/node/extfs';
import { isString } from 'vs/base/common/types';
import { Promise, TPromise } from 'vs/base/common/winjs.base';
import { download, asJson } from 'vs/base/node/request';
......@@ -42,7 +41,7 @@ export class Win32AutoUpdaterImpl extends EventEmitter implements IAutoUpdater {
get cachePath(): TPromise<string> {
const result = path.join(tmpdir(), `vscode-update-${process.arch}`);
return new TPromise<string>((c, e) => mkdirp(result, null, err => err ? e(err) : c(result)));
return pfs.mkdirp(result, null).then(() => result);
}
setFeedURL(url: string): void {
......
......@@ -34,6 +34,7 @@ import { TextModelResolverService } from 'vs/workbench/services/textmodelResolve
import { IChoiceService } from 'vs/platform/message/common/message';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { mkdirp } from 'vs/base/node/pfs';
class SettingsTestEnvironmentService extends EnvironmentService {
......@@ -80,21 +81,14 @@ suite('ConfigurationEditingService', () => {
.then(() => setUpServices());
});
function setUpWorkspace(): TPromise<void> {
return new TPromise<void>((c, e) => {
const id = uuid.generateUuid();
parentDir = path.join(os.tmpdir(), 'vsctests', id);
workspaceDir = path.join(parentDir, 'workspaceconfig', id);
globalSettingsFile = path.join(workspaceDir, 'config.json');
workspaceSettingsDir = path.join(workspaceDir, '.vscode');
extfs.mkdirp(workspaceSettingsDir, 493, (error) => {
if (error) {
e(error);
} else {
c(null);
}
});
});
function setUpWorkspace(): TPromise<boolean> {
const id = uuid.generateUuid();
parentDir = path.join(os.tmpdir(), 'vsctests', id);
workspaceDir = path.join(parentDir, 'workspaceconfig', id);
globalSettingsFile = path.join(workspaceDir, 'config.json');
workspaceSettingsDir = path.join(workspaceDir, '.vscode');
return mkdirp(workspaceSettingsDir, 493);
}
function setUpServices(noWorkspace: boolean = false): TPromise<void> {
......
......@@ -34,6 +34,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { mkdirp } from 'vs/base/node/pfs';
class SettingsTestEnvironmentService extends EnvironmentService {
......@@ -53,15 +54,7 @@ function setUpFolderWorkspace(folderName: string): TPromise<{ parentDir: string,
function setUpFolder(folderName: string, parentDir: string): TPromise<string> {
const folderDir = path.join(parentDir, folderName);
const workspaceSettingsDir = path.join(folderDir, '.vscode');
return new TPromise((c, e) => {
extfs.mkdirp(workspaceSettingsDir, 493, (error) => {
if (error) {
e(error);
return null;
}
c(folderDir);
});
});
return mkdirp(workspaceSettingsDir, 493).then(() => folderDir);
}
function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, configPath: string }> {
......@@ -69,7 +62,7 @@ function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, config
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
return createDir(parentDir)
return mkdirp(parentDir, 493)
.then(() => {
const configPath = path.join(parentDir, 'vsctests.code-workspace');
const workspace = { folders: folders.map(path => ({ path })) };
......@@ -81,17 +74,6 @@ function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, config
}
function createDir(dir: string): TPromise<void> {
return new TPromise((c, e) => {
extfs.mkdirp(dir, 493, (error) => {
if (error) {
e(error);
return null;
}
c(null);
});
});
}
suite('WorkspaceContextService - Folder', () => {
......
......@@ -43,6 +43,7 @@ import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybindin
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { mkdirp } from 'vs/base/node/pfs';
interface Modifiers {
metaKey?: boolean;
......@@ -87,17 +88,9 @@ suite('Keybindings Editing', () => {
});
});
function setUpWorkspace(): TPromise<void> {
return new TPromise<void>((c, e) => {
testDir = path.join(os.tmpdir(), 'vsctests', uuid.generateUuid());
extfs.mkdirp(testDir, 493, (error) => {
if (error) {
e(error);
} else {
c(null);
}
});
});
function setUpWorkspace(): TPromise<boolean> {
testDir = path.join(os.tmpdir(), 'vsctests', uuid.generateUuid());
return mkdirp(testDir, 493);
}
teardown(() => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册