| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Tobias Koppers @sokra*/var normalize = require("./normalize");var errors = require("errno");var stream = require("readable-stream");var ReadableStream = stream.Readable;var WritableStream = stream.Writable;function MemoryFileSystemError(err, path) {	Error.call(this)	if (Error.captureStackTrace)		Error.captureStackTrace(this, arguments.callee)	this.code = err.code;	this.errno = err.errno;	this.message = err.description;	this.path = path;}MemoryFileSystemError.prototype = new Error();function MemoryFileSystem(data) {	this.data = data || {};}module.exports = MemoryFileSystem;function isDir(item) {	if(typeof item !== "object") return false;	return item[""] === true;}function isFile(item) {	if(typeof item !== "object") return false;	return !item[""];}function pathToArray(path) {	path = normalize(path);	var nix = /^\//.test(path);	if(!nix) {		if(!/^[A-Za-z]:/.test(path)) {			throw new MemoryFileSystemError(errors.code.EINVAL, path);		}		path = path.replace(/[\\\/]+/g, "\\"); // multi slashs		path = path.split(/[\\\/]/);		path[0] = path[0].toUpperCase();	} else {		path = path.replace(/\/+/g, "/"); // multi slashs		path = path.substr(1).split("/");	}	if(!path[path.length-1]) path.pop();	return path;}function trueFn() { return true; }function falseFn() { return false; }MemoryFileSystem.prototype.meta = function(_path) {	var path = pathToArray(_path);	var current = this.data;	for(var i = 0; i < path.length - 1; i++) {		if(!isDir(current[path[i]]))			return;		current = current[path[i]];	}	return current[path[i]];}MemoryFileSystem.prototype.existsSync = function(_path) {	return !!this.meta(_path);}MemoryFileSystem.prototype.statSync = function(_path) {	var current = this.meta(_path);	if(_path === "/" || isDir(current)) {		return {			isFile: falseFn,			isDirectory: trueFn,			isBlockDevice: falseFn,			isCharacterDevice: falseFn,			isSymbolicLink: falseFn,			isFIFO: falseFn,			isSocket: falseFn		};	} else if(isFile(current)) {		return {			isFile: trueFn,			isDirectory: falseFn,			isBlockDevice: falseFn,			isCharacterDevice: falseFn,			isSymbolicLink: falseFn,			isFIFO: falseFn,			isSocket: falseFn		};	} else {		throw new MemoryFileSystemError(errors.code.ENOENT, _path);	}};MemoryFileSystem.prototype.readFileSync = function(_path, encoding) {	var path = pathToArray(_path);	var current = this.data;	for(var i = 0; i < path.length - 1; i++) {		if(!isDir(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOENT, _path);		current = current[path[i]];	}	if(!isFile(current[path[i]])) {		if(isDir(current[path[i]]))			throw new MemoryFileSystemError(errors.code.EISDIR, _path);		else			throw new MemoryFileSystemError(errors.code.ENOENT, _path);	}	current = current[path[i]];	return encoding ? current.toString(encoding) : current;};MemoryFileSystem.prototype.readdirSync = function(_path) {	if(_path === "/") return Object.keys(this.data).filter(Boolean);	var path = pathToArray(_path);	var current = this.data;	for(var i = 0; i < path.length - 1; i++) {		if(!isDir(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOENT, _path);		current = current[path[i]];	}	if(!isDir(current[path[i]])) {		if(isFile(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOTDIR, _path);		else			throw new MemoryFileSystemError(errors.code.ENOENT, _path);	}	return Object.keys(current[path[i]]).filter(Boolean);};MemoryFileSystem.prototype.mkdirpSync = function(_path) {	var path = pathToArray(_path);	if(path.length === 0) return;	var current = this.data;	for(var i = 0; i < path.length; i++) {		if(isFile(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOTDIR, _path);		else if(!isDir(current[path[i]]))			current[path[i]] = {"":true};		current = current[path[i]];	}	return;};MemoryFileSystem.prototype.mkdirSync = function(_path) {	var path = pathToArray(_path);	if(path.length === 0) return;	var current = this.data;	for(var i = 0; i < path.length - 1; i++) {		if(!isDir(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOENT, _path);		current = current[path[i]];	}	if(isDir(current[path[i]]))		throw new MemoryFileSystemError(errors.code.EEXIST, _path);	else if(isFile(current[path[i]]))		throw new MemoryFileSystemError(errors.code.ENOTDIR, _path);	current[path[i]] = {"":true};	return;};MemoryFileSystem.prototype._remove = function(_path, name, testFn) {	var path = pathToArray(_path);	if(path.length === 0) {		throw new MemoryFileSystemError(errors.code.EPERM, _path);	}	var current = this.data;	for(var i = 0; i < path.length - 1; i++) {		if(!isDir(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOENT, _path);		current = current[path[i]];	}	if(!testFn(current[path[i]]))		throw new MemoryFileSystemError(errors.code.ENOENT, _path);	delete current[path[i]];	return;};MemoryFileSystem.prototype.rmdirSync = function(_path) {	return this._remove(_path, "Directory", isDir);};MemoryFileSystem.prototype.unlinkSync = function(_path) {	return this._remove(_path, "File", isFile);};MemoryFileSystem.prototype.readlinkSync = function(_path) {	throw new MemoryFileSystemError(errors.code.ENOSYS, _path);};MemoryFileSystem.prototype.writeFileSync = function(_path, content, encoding) {	if(!content && !encoding) throw new Error("No content");	var path = pathToArray(_path);	if(path.length === 0) {		throw new MemoryFileSystemError(errors.code.EISDIR, _path);	}	var current = this.data;	for(var i = 0; i < path.length - 1; i++) {		if(!isDir(current[path[i]]))			throw new MemoryFileSystemError(errors.code.ENOENT, _path);		current = current[path[i]];	}	if(isDir(current[path[i]]))		throw new MemoryFileSystemError(errors.code.EISDIR, _path);	current[path[i]] = encoding || typeof content === "string" ? new Buffer(content, encoding) : content;	return;};MemoryFileSystem.prototype.join = require("./join");MemoryFileSystem.prototype.pathToArray = pathToArray;MemoryFileSystem.prototype.normalize = normalize;// stream functionsMemoryFileSystem.prototype.createReadStream = function(path, options) {	var stream = new ReadableStream();	var done = false;	var data;	try {		data = this.readFileSync(path);	} catch (e) {		stream._read = function() {			if (done) {				return;			}			done = true;			this.emit('error', e);			this.push(null);		};		return stream;	}	options = options || { };	options.start = options.start || 0;	options.end = options.end || data.length;	stream._read = function() {		if (done) {			return;		}		done = true;		this.push(data.slice(options.start, options.end));		this.push(null);	};	return stream;};MemoryFileSystem.prototype.createWriteStream = function(path, options) {	var stream = new WritableStream(), self = this;	try {		// Zero the file and make sure it is writable		this.writeFileSync(path, new Buffer(0));	} catch(e) {		// This or setImmediate?		stream.once('prefinish', function() {			stream.emit('error', e);		});		return stream;	}	var bl = [ ], len = 0;	stream._write = function(chunk, encoding, callback) {		bl.push(chunk);		len += chunk.length;		self.writeFile(path, Buffer.concat(bl, len), callback);	}	return stream;};// async functions["stat", "readdir", "mkdirp", "rmdir", "unlink", "readlink"].forEach(function(fn) {	MemoryFileSystem.prototype[fn] = function(path, callback) {		try {			var result = this[fn + "Sync"](path);		} catch(e) {			setImmediate(function() {				callback(e);			});			return;		}		setImmediate(function() {			callback(null, result);		});	};});["mkdir", "readFile"].forEach(function(fn) {	MemoryFileSystem.prototype[fn] = function(path, optArg, callback) {		if(!callback) {			callback = optArg;			optArg = undefined;		}		try {			var result = this[fn + "Sync"](path, optArg);		} catch(e) {			setImmediate(function() {				callback(e);			});			return;		}		setImmediate(function() {			callback(null, result);		});	};});MemoryFileSystem.prototype.exists = function(path, callback) {	return callback(this.existsSync(path));}MemoryFileSystem.prototype.writeFile = function (path, content, encoding, callback) {	if(!callback) {		callback = encoding;		encoding = undefined;	}	try {		this.writeFileSync(path, content, encoding);	} catch(e) {		return callback(e);	}	return callback();};
 |