From a28feae506f23c6a899d283656e5622fe4070055 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Tue, 18 Mar 2014 16:34:47 -0400 Subject: [PATCH] Fix failing tests for src/filesystem/* issues, all tests pass now --- src/filesystem/implementation.js | 91 +++-- src/filesystem/interface.js | 551 ++++--------------------------- 2 files changed, 124 insertions(+), 518 deletions(-) diff --git a/src/filesystem/implementation.js b/src/filesystem/implementation.js index 0d579f3..332ebba 100644 --- a/src/filesystem/implementation.js +++ b/src/filesystem/implementation.js @@ -1247,7 +1247,7 @@ define(function(require) { } } - function setxattr_file (context, path, name, value, flag, callback) { + function setxattr_file(context, path, name, value, flag, callback) { path = normalize(path); if (typeof name != 'string') { @@ -1440,19 +1440,11 @@ define(function(require) { return true; } - // node.js supports a calling pattern that leaves off a callback. - function maybeCallback(callback) { - if(typeof callback === "function") { - return callback; - } - return function(err) { - if(err) { - throw err; - } - }; - } - function open(fs, context, path, flags, callback) { + function open(fs, context, path, flags, mode, callback) { + // NOTE: we support the same signature as node with a `mode` arg, + // but ignore it. + callback = arguments[arguments.length - 1]; if(!pathCheck(path, callback)) return; function check_result(error, fileNode) { @@ -1479,7 +1471,7 @@ define(function(require) { open_file(context, path, flags, check_result); } - function close(fs, fd, callback) { + function close(fs, context, fd, callback) { if(!_(fs.openFiles).has(fd)) { callback(new Errors.EBADF()); } else { @@ -1488,24 +1480,26 @@ define(function(require) { } } - function mkdir(context, path, callback) { + function mkdir(fs, context, path, mode, callback) { + // NOTE: we support passing a mode arg, but we ignore it internally for now. + callback = arguments[arguments.length - 1]; if(!pathCheck(path, callback)) return; make_directory(context, path, standard_check_result_cb(callback)); } - function rmdir(context, path, callback) { + function rmdir(fs, context, path, callback) { if(!pathCheck(path, callback)) return; remove_directory(context, path, standard_check_result_cb(callback)); } - function stat(context, name, path, callback) { + function stat(fs, context, path, callback) { if(!pathCheck(path, callback)) return; function check_result(error, result) { if(error) { callback(error); } else { - var stats = new Stats(result, name); + var stats = new Stats(result, fs.name); callback(null, stats); } } @@ -1531,20 +1525,27 @@ define(function(require) { } } - function link(context, oldpath, newpath, callback) { + function link(fs, context, oldpath, newpath, callback) { if(!pathCheck(oldpath, callback)) return; if(!pathCheck(newpath, callback)) return; link_node(context, oldpath, newpath, standard_check_result_cb(callback)); } - function unlink(context, path, callback) { + function unlink(fs, context, path, callback) { if(!pathCheck(path, callback)) return; unlink_node(context, path, standard_check_result_cb(callback)); } function read(fs, context, fd, buffer, offset, length, position, callback) { + // Follow how node.js does this + function wrapped_cb(err, bytesRead) { + // Retain a reference to buffer so that it can't be GC'ed too soon. + callback(err, bytesRead || 0, buffer); + } + offset = (undefined === offset) ? 0 : offset; length = (undefined === length) ? buffer.length - offset : length; + callback = arguments[arguments.length - 1]; var ofd = fs.openFiles[fd]; if(!ofd) { @@ -1552,11 +1553,12 @@ define(function(require) { } else if(!_(ofd.flags).contains(O_READ)) { callback(new Errors.EBADF('descriptor does not permit reading')); } else { - read_data(context, ofd, buffer, offset, length, position, standard_check_result_cb(callback)); + read_data(context, ofd, buffer, offset, length, position, standard_check_result_cb(wrapped_cb)); } } function readFile(fs, context, path, options, callback) { + callback = arguments[arguments.length - 1]; options = validate_file_options(options, null, 'r'); if(!pathCheck(path, callback)) return; @@ -1601,6 +1603,7 @@ define(function(require) { } function write(fs, context, fd, buffer, offset, length, position, callback) { + callback = arguments[arguments.length - 1]; offset = (undefined === offset) ? 0 : offset; length = (undefined === length) ? buffer.length - offset : length; @@ -1617,6 +1620,7 @@ define(function(require) { } function writeFile(fs, context, path, data, options, callback) { + callback = arguments[arguments.length - 1]; options = validate_file_options(options, 'utf8', 'w'); if(!pathCheck(path, callback)) return; @@ -1652,6 +1656,7 @@ define(function(require) { } function appendFile(fs, context, path, data, options, callback) { + callback = arguments[arguments.length - 1]; options = validate_file_options(options, 'utf8', 'a'); if(!pathCheck(path, callback)) return; @@ -1686,14 +1691,14 @@ define(function(require) { }); } - function exists(context, name, path, callback) { + function exists(fs, context, path, callback) { function cb(err, stats) { callback(err ? false : true); } - stat(context, name, path, cb); + stat(fs, context, path, cb); } - function getxattr(context, path, name, callback) { + function getxattr(fs, context, path, name, callback) { if (!pathCheck(path, callback)) return; getxattr_file(context, path, name, standard_check_result_cb(callback)); } @@ -1708,12 +1713,22 @@ define(function(require) { } } - function setxattr(context, path, name, value, flag, callback) { + function setxattr(fs, context, path, name, value, flag, callback) { + if(typeof flag === 'function') { + callback = flag; + flag = null; + } + if (!pathCheck(path, callback)) return; setxattr_file(context, path, name, value, flag, standard_check_result_cb(callback)); } function fsetxattr(fs, context, fd, name, value, flag, callback) { + if(typeof flag === 'function') { + callback = flag; + flag = null; + } + var ofd = fs.openFiles[fd]; if (!ofd) { callback(new Errors.EBADF()); @@ -1726,9 +1741,9 @@ define(function(require) { } } - function removexattr(context, path, name, callback) { + function removexattr(fs, context, path, name, callback) { if (!pathCheck(path, callback)) return; - removexattr_file (context, path, name, standard_check_result_cb(callback)); + removexattr_file(context, path, name, standard_check_result_cb(callback)); } function fremovexattr(fs, context, fd, name, callback) { @@ -1784,12 +1799,12 @@ define(function(require) { } } - function readdir(context, path, callback) { + function readdir(fs, context, path, callback) { if(!pathCheck(path, callback)) return; read_directory(context, path, standard_check_result_cb(callback)); } - function utimes(context, path, atime, mtime, callback) { + function utimes(fs, context, path, atime, mtime, callback) { if(!pathCheck(path, callback)) return; var currentTime = Date.now(); @@ -1814,7 +1829,7 @@ define(function(require) { } } - function rename(context, oldpath, newpath, callback) { + function rename(fs, context, oldpath, newpath, callback) { if(!pathCheck(oldpath, callback)) return; if(!pathCheck(newpath, callback)) return; @@ -1829,13 +1844,15 @@ define(function(require) { link_node(context, oldpath, newpath, unlink_old_node); } - function symlink(context, srcpath, dstpath, callback) { + function symlink(fs, context, srcpath, dstpath, type, callback) { + // NOTE: we support passing the `type` arg, but ignore it. + callback = arguments[arguments.length - 1]; if(!pathCheck(srcpath, callback)) return; if(!pathCheck(dstpath, callback)) return; make_symbolic_link(context, srcpath, dstpath, standard_check_result_cb(callback)); } - function readlink(context, path, callback) { + function readlink(fs, context, path, callback) { if(!pathCheck(path, callback)) return; read_link(context, path, standard_check_result_cb(callback)); } @@ -1855,12 +1872,20 @@ define(function(require) { lstat_file(context, path, check_result); } - function truncate(context, path, length, callback) { + function truncate(fs, context, path, length, callback) { + // NOTE: length is optional + callback = arguments[arguments.length - 1]; + length = length || 0; + if(!pathCheck(path, callback)) return; truncate_file(context, path, length, standard_check_result_cb(callback)); } function ftruncate(fs, context, fd, length, callback) { + // NOTE: length is optional + callback = arguments[arguments.length - 1]; + length = length || 0; + var ofd = fs.openFiles[fd]; if(!ofd) { callback(new Errors.EBADF()); diff --git a/src/filesystem/interface.js b/src/filesystem/interface.js index 700e249..373ec9d 100644 --- a/src/filesystem/interface.js +++ b/src/filesystem/interface.js @@ -10,8 +10,6 @@ define(function(require) { var FS_READY = require('src/constants').FS_READY; var FS_PENDING = require('src/constants').FS_PENDING; var FS_ERROR = require('src/constants').FS_ERROR; - var FS_NOMTIME = require('src/constants').FS_NOMTIME; - var FS_NOCTIME = require('src/constants').FS_NOCTIME; var providers = require('src/providers/providers'); var adapters = require('src/adapters/adapters'); @@ -36,7 +34,7 @@ define(function(require) { }; } - /* + /** * FileSystem * * A FileSystem takes an `options` object, which can specify a number of, @@ -65,9 +63,10 @@ define(function(require) { options = options || {}; callback = callback || nop; - var name = options.name || FILE_SYSTEM_NAME; var flags = options.flags; - var provider = options.provider || new providers.Default(name); + var provider = options.provider || new providers.Default(options.name || FILE_SYSTEM_NAME); + // If we're given a provider, match its name unless we get an explicit name + var name = options.name || provider.name; var forceFormatting = _(flags).contains(FS_FORMAT); var fs = this; @@ -211,497 +210,79 @@ define(function(require) { // Expose adatpers on FileSystem constructor FileSystem.adapters = adapters; - /** * Public API for FileSystem */ + [ + 'open', + 'close', + 'mkdir', + 'rmdir', + 'stat', + 'fstat', + 'link', + 'unlink', + 'read', + 'readFile', + 'write', + 'writeFile', + 'appendFile', + 'exists', + 'lseek', + 'readdir', + 'rename', + 'readlink', + 'symlink', + 'lstat', + 'truncate', + 'ftruncate', + 'utimes', + 'futimes', + 'setxattr', + 'getxattr', + 'fsetxattr', + 'fgetxattr', + 'removexattr', + 'fremovexattr' + ].forEach(function(methodName) { + FileSystem.prototype[methodName] = function() { + var fs = this; + var args = Array.prototype.slice.call(arguments, 0); + var lastArgIndex = args.length - 1; - FileSystem.prototype.open = function(path, flags, mode, callback) { - // We support the same signature as node with a `mode` arg, but - // ignore it. Find the callback. - callback = maybeCallback(arguments[arguments.length - 1]); - var fs = this; - var error = fs.queueOrRun( - function() { + // We may or may not get a callback, and since node.js supports + // fire-and-forget style fs operations, we have to dance a bit here. + var missingCallback = typeof args[lastArgIndex] !== 'function'; + var callback = maybeCallback(args[lastArgIndex]); + + var error = fs.queueOrRun(function() { var context = fs.provider.openReadWriteContext(); + + // Wrap the callback so we can explicitly close the context function complete() { context.close(); callback.apply(fs, arguments); } - impl.open(fs, context, path, flags, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.close = function(fd, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); + + // Either add or replace the callback with our wrapper complete() + if(missingCallback) { + args.push(complete); + } else { + args[lastArgIndex] = complete; } - impl.close(fs, fd, complete); + + // Forward this call to the impl's version, using the following + // call signature, with complete() as the callback/last-arg now: + // fn(fs, context, arg0, arg1, ... , complete); + var fnArgs = [fs, context].concat(args); + impl[methodName].apply(null, fnArgs); + }); + if(error) { + callback(error); } - ); - if(error) callback(error); - }; - FileSystem.prototype.mkdir = function(path, mode, callback) { - // Support passing a mode arg, but we ignore it internally for now. - if(typeof mode === 'function') { - callback = mode; - } - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.mkdir(context, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.rmdir = function(path, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.rmdir(context, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.stat = function(path, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.stat(context, fs.name, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.fstat = function(fd, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.fstat(fs, context, fd, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.link = function(oldpath, newpath, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.link(context, oldpath, newpath, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.unlink = function(path, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.unlink(context, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.read = function(fd, buffer, offset, length, position, callback) { - // Follow how node.js does this - callback = maybeCallback(callback); - function wrapper(err, bytesRead) { - // Retain a reference to buffer so that it can't be GC'ed too soon. - callback(err, bytesRead || 0, buffer); - } - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - wrapper.apply(this, arguments); - } - impl.read(fs, context, fd, buffer, offset, length, position, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.readFile = function(path, options, callback_) { - var callback = maybeCallback(arguments[arguments.length - 1]); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.readFile(fs, context, path, options, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.write = function(fd, buffer, offset, length, position, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.write(fs, context, fd, buffer, offset, length, position, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.writeFile = function(path, data, options, callback_) { - var callback = maybeCallback(arguments[arguments.length - 1]); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.writeFile(fs, context, path, data, options, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.appendFile = function(path, data, options, callback_) { - var callback = maybeCallback(arguments[arguments.length - 1]); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.appendFile(fs, context, path, data, options, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.exists = function(path, callback_) { - var callback = maybeCallback(arguments[arguments.length - 1]); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.exists(context, fs.name, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.lseek = function(fd, offset, whence, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.lseek(fs, context, fd, offset, whence, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.readdir = function(path, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.readdir(context, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.rename = function(oldpath, newpath, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.rename(context, oldpath, newpath, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.readlink = function(path, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.readlink(context, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.symlink = function(srcpath, dstpath, type, callback_) { - // Follow node.js in allowing the `type` arg to be passed, but we ignore it. - var callback = maybeCallback(arguments[arguments.length - 1]); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.symlink(context, srcpath, dstpath, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.lstat = function(path, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.lstat(fs, context, path, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.truncate = function(path, length, callback) { - // Follow node.js in allowing the `length` to be optional - if(typeof length === 'function') { - callback = length; - length = 0; - } - callback = maybeCallback(callback); - length = typeof length === 'number' ? length : 0; - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.truncate(context, path, length, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.ftruncate = function(fd, length, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function() { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.ftruncate(fs, context, fd, length, complete); - } - ); - if(error) callback(error); - }; - FileSystem.prototype.utimes = function(path, atime, mtime, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.utimes(context, path, atime, mtime, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.futimes = function(fd, atime, mtime, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.futimes(fs, context, fd, atime, mtime, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.setxattr = function (path, name, value, flag, callback) { - callback = maybeCallback(arguments[arguments.length - 1]); - var _flag = (typeof flag != 'function') ? flag : null; - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.setxattr(context, path, name, value, _flag, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.getxattr = function (path, name, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.getxattr(context, path, name, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.fsetxattr = function (fd, name, value, flag, callback) { - callback = maybeCallback(arguments[arguments.length - 1]); - var _flag = (typeof flag != 'function') ? flag : null; - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.fsetxattr(fs, context, fd, name, value, _flag, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.fgetxattr = function (fd, name, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.fgetxattr(fs, context, fd, name, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.removexattr = function (path, name, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.removexattr(context, path, name, complete); - } - ); - if (error) { - callback(error); - } - }; - FileSystem.prototype.fremovexattr = function (fd, name, callback) { - callback = maybeCallback(callback); - var fs = this; - var error = fs.queueOrRun( - function () { - var context = fs.provider.openReadWriteContext(); - function complete() { - context.close(); - callback.apply(fs, arguments); - } - impl.fremovexattr(fs, context, fd, name, complete); - } - ); - if (error) { - callback(error); - } - }; + }; + }); + FileSystem.prototype.Shell = function(options) { return new Shell(this, options); };