diff --git a/dist/filer-test.js b/dist/filer-test.js index 2181c93..41b5180 100644 --- a/dist/filer-test.js +++ b/dist/filer-test.js @@ -1,3 +1,4 @@ +/* Test file for filerjs v0.0.36*/ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require("JkpR2F")) +},{"JkpR2F":42}],42:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -6607,7 +6836,1379 @@ process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; -},{}],42:[function(require,module,exports){ +},{}],43:[function(require,module,exports){ +(function (process){ +;(function (require, exports, module, platform) { + +if (module) module.exports = minimatch +else exports.minimatch = minimatch + +if (!require) { + require = function (id) { + switch (id) { + case "sigmund": return function sigmund (obj) { + return JSON.stringify(obj) + } + case "path": return { basename: function (f) { + f = f.split(/[\/\\]/) + var e = f.pop() + if (!e) e = f.pop() + return e + }} + case "lru-cache": return function LRUCache () { + // not quite an LRU, but still space-limited. + var cache = {} + var cnt = 0 + this.set = function (k, v) { + cnt ++ + if (cnt >= 100) cache = {} + cache[k] = v + } + this.get = function (k) { return cache[k] } + } + } + } +} + +minimatch.Minimatch = Minimatch + +var LRU = require("lru-cache") + , cache = minimatch.cache = new LRU({max: 100}) + , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} + , sigmund = require("sigmund") + +var path = require("path") + // any single thing other than / + // don't need to escape / when using new RegExp() + , qmark = "[^/]" + + // * => any number of characters + , star = qmark + "*?" + + // ** when dots are allowed. Anything goes, except .. and . + // not (^ or / followed by one or two dots followed by $ or /), + // followed by anything, any number of times. + , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" + + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" + + // characters that need to be escaped in RegExp. + , reSpecials = charSet("().*{}+?[]^$\\!") + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split("").reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + return false + } + + // "" only matches "" + if (pattern.trim() === "") return p === "" + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options, cache) + } + + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + pattern = pattern.split("\\").join("/") + } + + // lru storage. + // these things aren't particularly big, but walking down the string + // and turning it into a regexp can get pretty costly. + var cacheKey = pattern + "\n" + sigmund(options) + var cached = minimatch.cache.get(cacheKey) + if (cached) return cached + minimatch.cache.set(cacheKey, this) + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.debug = function() {} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) this.debug = console.error + + this.debug(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + this.debug(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + this.debug(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + , negate = false + , options = this.options + , negateOffset = 0 + + if (options.nonegate) return + + for ( var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === "!" + ; i ++) { + negate = !negate + negateOffset ++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return new Minimatch(pattern, options).braceExpand() +} + +Minimatch.prototype.braceExpand = braceExpand + +function pad(n, width, z) { + z = z || '0'; + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; +} + +function braceExpand (pattern, options) { + options = options || this.options + pattern = typeof pattern === "undefined" + ? this.pattern : pattern + + if (typeof pattern === "undefined") { + throw new Error("undefined pattern") + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + var escaping = false + + // examples and comments refer to this crazy pattern: + // a{b,c{d,e},{f,g}h}x{y,z} + // expected: + // abxy + // abxz + // acdxy + // acdxz + // acexy + // acexz + // afhxy + // afhxz + // aghxy + // aghxz + + // everything before the first \{ is just a prefix. + // So, we pluck that off, and work with the rest, + // and then prepend it to everything we find. + if (pattern.charAt(0) !== "{") { + this.debug(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + this.debug(i, c) + if (c === "\\") { + escaping = !escaping + } else if (c === "{" && !escaping) { + prefix = pattern.substr(0, i) + break + } + } + + // actually no sets, all { were escaped. + if (prefix === null) { + this.debug("no sets") + return [pattern] + } + + var tail = braceExpand.call(this, pattern.substr(i), options) + return tail.map(function (t) { + return prefix + t + }) + } + + // now we have something like: + // {b,c{d,e},{f,g}h}x{y,z} + // walk through the set, expanding each part, until + // the set ends. then, we'll expand the suffix. + // If the set only has a single member, then'll put the {} back + + // first, handle numeric sets, since they're easier + var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) + if (numset) { + this.debug("numset", numset[1], numset[2]) + var suf = braceExpand.call(this, pattern.substr(numset[0].length), options) + , start = +numset[1] + , needPadding = numset[1][0] === '0' + , startWidth = numset[1].length + , padded + , end = +numset[2] + , inc = start > end ? -1 : 1 + , set = [] + + for (var i = start; i != (end + inc); i += inc) { + padded = needPadding ? pad(i, startWidth) : i + '' + // append all the suffixes + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + set.push(padded + suf[ii]) + } + } + return set + } + + // ok, walk through the set + // We hope, somewhat optimistically, that there + // will be a } at the end. + // If the closing brace isn't found, then the pattern is + // interpreted as braceExpand("\\" + pattern) so that + // the leading \{ will be interpreted literally. + var i = 1 // skip the \{ + , depth = 1 + , set = [] + , member = "" + , sawEnd = false + , escaping = false + + function addMember () { + set.push(member) + member = "" + } + + this.debug("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + this.debug("", i, c) + + if (escaping) { + escaping = false + member += "\\" + c + } else { + switch (c) { + case "\\": + escaping = true + continue + + case "{": + depth ++ + member += "{" + continue + + case "}": + depth -- + // if this closes the actual set, then we're done + if (depth === 0) { + addMember() + // pluck off the close-brace + i ++ + break FOR + } else { + member += c + continue + } + + case ",": + if (depth === 1) { + addMember() + } else { + member += c + } + continue + + default: + member += c + continue + } // switch + } // else + } // for + + // now we've either finished the set, and the suffix is + // pattern.substr(i), or we have *not* closed the set, + // and need to escape the leading brace + if (depth !== 0) { + this.debug("didn't close", pattern) + return braceExpand.call(this, "\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + this.debug("set", set) + this.debug("suffix", pattern.substr(i)) + var suf = braceExpand.call(this, pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + this.debug("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand.call(this, p, options) + }, this) + this.debug("set expanded", set) + + + // [["b"], ["cd", "ce"], ["fh", "gh"]] -> + // ["b", "cd", "ce", "fh", "gh"] + set = set.reduce(function (l, r) { + return l.concat(r) + }) + + if (addBraces) { + set = set.map(function (s) { + return "{" + s + "}" + }) + } + + // now attach the suffixes. + var ret = [] + for (var i = 0, l = set.length; i < l; i ++) { + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + ret.push(set[i] + suf[ii]) + } + } + return ret +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === "**") return GLOBSTAR + if (pattern === "") return "" + + var re = "" + , hasMagic = !!options.nocase + , escaping = false + // ? => one single character + , patternListStack = [] + , plType + , stateChar + , inClass = false + , reClassStart = -1 + , classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + , patternStart = pattern.charAt(0) === "." ? "" // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" + : "(?!\\.)" + , self = this + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += star + hasMagic = true + break + case "?": + re += qmark + hasMagic = true + break + default: + re += "\\"+stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + this.debug("%s\t%s %s %j", pattern, i, re, c) + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += "\\" + c + escaping = false + continue + } + + SWITCH: switch (c) { + case "/": + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case "\\": + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case "?": + case "*": + case "+": + case "@": + case "!": + this.debug("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === "!" && i === classStart + 1) c = "^" + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case "(": + if (inClass) { + re += "(" + continue + } + + if (!stateChar) { + re += "\\(" + continue + } + + plType = stateChar + patternListStack.push({ type: plType + , start: i - 1 + , reStart: re.length }) + // negation is (?:(?!js)[^/]*) + re += stateChar === "!" ? "(?:(?!" : "(?:" + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + clearStateChar() + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + switch (plType) { + case "!": + re += "[^/]*?)" + break + case "?": + case "+": + case "*": re += plType + case "@": break // the default anyway + } + continue + + case "|": + if (inClass || !patternListStack.length || escaping) { + re += "\\|" + escaping = false + continue + } + + clearStateChar() + re += "|" + continue + + // these are mostly the same in regexp and glob + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += "\\" + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case "]": + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += "\\" + c + escaping = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === "^" && inClass)) { + re += "\\" + } + + re += c + + } // switch + } // for + + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + var cs = pattern.substr(classStart + 1) + , sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + "\\[" + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + var pl + while (pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + 3) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = "\\" + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + "|" + }) + + this.debug("tail=%j\n %s", tail, tail) + var t = pl.type === "*" ? star + : pl.type === "?" ? qmark + : "\\" + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + + t + "\\(" + + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += "\\\\" + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case ".": + case "[": + case "(": addPatternStart = true + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== "" && hasMagic) re = "(?=.)" + re + + if (addPatternStart) re = patternStart + re + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [ re, hasMagic ] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? "i" : "" + , regExp = new RegExp("^" + re + "$", flags) + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) return this.regexp = false + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + , flags = options.nocase ? "i" : "" + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === "string") ? regExpEscape(p) + : p._src + }).join("\\\/") + }).join("|") + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^(?:" + re + ")$" + + // can match anything, as long as it's not this. + if (this.negate) re = "^(?!" + re + ").*$" + + try { + return this.regexp = new RegExp(re, flags) + } catch (ex) { + return this.regexp = false + } +} + +minimatch.match = function (list, pattern, options) { + options = options || {} + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + this.debug("match", f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === "" + + if (f === "/" && partial) return true + + var options = this.options + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + f = f.split("\\").join("/") + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, "split", f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + this.debug(this.pattern, "set", set) + + // Find the basename of the path by looking for the last non-empty segment + var filename; + for (var i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break + } + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i], file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + this.debug("matchOne", + { "this": this + , file: file + , pattern: pattern }) + + this.debug("matchOne", file.length, pattern.length) + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + this.debug("matchOne loop") + var p = pattern[pi] + , f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + , pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for ( ; fi < fl; fi ++) { + if (file[fi] === "." || file[fi] === ".." || + (!options.dot && file[fi].charAt(0) === ".")) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + WHILE: while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', + file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === "." || swallowee === ".." || + (!options.dot && swallowee.charAt(0) === ".")) { + this.debug("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr ++ + } + } + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug("\n>>> no match, partial?", file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === "string") { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug("string match", p, f, hit) + } else { + hit = f.match(p) + this.debug("pattern match", p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") + return emptyFileEnd + } + + // should be unreachable. + throw new Error("wtf?") +} + + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, "$1") +} + + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} + +})( typeof require === "function" ? require : null, + this, + typeof module === "object" ? module : null, + typeof process === "object" ? process.platform : "win32" + ) + +}).call(this,require("JkpR2F")) +},{"JkpR2F":42,"lru-cache":44,"path":41,"sigmund":45}],44:[function(require,module,exports){ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) + return new LRUCache(options) + + if (typeof options === 'number') + options = { max: options } + + if (!options) + options = {} + + this._max = options.max + // Kind of weird to have a default max of Infinity, but oh well. + if (!this._max || !(typeof this._max === "number") || this._max <= 0 ) + this._max = Infinity + + this._lengthCalculator = options.length || naiveLength + if (typeof this._lengthCalculator !== "function") + this._lengthCalculator = naiveLength + + this._allowStale = options.stale || false + this._maxAge = options.maxAge || null + this._dispose = options.dispose + this.reset() +} + +// resize the cache when the max changes. +Object.defineProperty(LRUCache.prototype, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + this._max = mL + if (this._length > this._max) trim(this) + } + , get : function () { return this._max } + , enumerable : true + }) + +// resize the cache when the lengthCalculator changes. +Object.defineProperty(LRUCache.prototype, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + this._lengthCalculator = naiveLength + this._length = this._itemCount + for (var key in this._cache) { + this._cache[key].length = 1 + } + } else { + this._lengthCalculator = lC + this._length = 0 + for (var key in this._cache) { + this._cache[key].length = this._lengthCalculator(this._cache[key].value) + this._length += this._cache[key].length + } + } + + if (this._length > this._max) trim(this) + } + , get : function () { return this._lengthCalculator } + , enumerable : true + }) + +Object.defineProperty(LRUCache.prototype, "length", + { get : function () { return this._length } + , enumerable : true + }) + + +Object.defineProperty(LRUCache.prototype, "itemCount", + { get : function () { return this._itemCount } + , enumerable : true + }) + +LRUCache.prototype.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + i++ + var hit = this._lruList[k] + if (this._maxAge && (Date.now() - hit.now > this._maxAge)) { + del(this, hit) + if (!this._allowStale) hit = undefined + } + if (hit) { + fn.call(thisp, hit.value, hit.key, this) + } + } +} + +LRUCache.prototype.keys = function () { + var keys = new Array(this._itemCount) + var i = 0 + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + keys[i++] = hit.key + } + return keys +} + +LRUCache.prototype.values = function () { + var values = new Array(this._itemCount) + var i = 0 + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + values[i++] = hit.value + } + return values +} + +LRUCache.prototype.reset = function () { + if (this._dispose && this._cache) { + for (var k in this._cache) { + this._dispose(k, this._cache[k].value) + } + } + + this._cache = Object.create(null) // hash of items by key + this._lruList = Object.create(null) // list of items in order of use recency + this._mru = 0 // most recently used + this._lru = 0 // least recently used + this._length = 0 // number of items in the list + this._itemCount = 0 +} + +// Provided for debugging/dev purposes only. No promises whatsoever that +// this API stays stable. +LRUCache.prototype.dump = function () { + return this._cache +} + +LRUCache.prototype.dumpLru = function () { + return this._lruList +} + +LRUCache.prototype.set = function (key, value) { + if (hOP(this._cache, key)) { + // dispose of the old one before overwriting + if (this._dispose) this._dispose(key, this._cache[key].value) + if (this._maxAge) this._cache[key].now = Date.now() + this._cache[key].value = value + this.get(key) + return true + } + + var len = this._lengthCalculator(value) + var age = this._maxAge ? Date.now() : 0 + var hit = new Entry(key, value, this._mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > this._max) { + if (this._dispose) this._dispose(key, value) + return false + } + + this._length += hit.length + this._lruList[hit.lu] = this._cache[key] = hit + this._itemCount ++ + + if (this._length > this._max) trim(this) + return true +} + +LRUCache.prototype.has = function (key) { + if (!hOP(this._cache, key)) return false + var hit = this._cache[key] + if (this._maxAge && (Date.now() - hit.now > this._maxAge)) { + return false + } + return true +} + +LRUCache.prototype.get = function (key) { + return get(this, key, true) +} + +LRUCache.prototype.peek = function (key) { + return get(this, key, false) +} + +LRUCache.prototype.pop = function () { + var hit = this._lruList[this._lru] + del(this, hit) + return hit || null +} + +LRUCache.prototype.del = function (key) { + del(this, this._cache[key]) +} + +function get (self, key, doUse) { + var hit = self._cache[key] + if (hit) { + if (self._maxAge && (Date.now() - hit.now > self._maxAge)) { + del(self, hit) + if (!self._allowStale) hit = undefined + } else { + if (doUse) use(self, hit) + } + if (hit) hit = hit.value + } + return hit +} + +function use (self, hit) { + shiftLU(self, hit) + hit.lu = self._mru ++ + self._lruList[hit.lu] = hit +} + +function trim (self) { + while (self._lru < self._mru && self._length > self._max) + del(self, self._lruList[self._lru]) +} + +function shiftLU (self, hit) { + delete self._lruList[ hit.lu ] + while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++ +} + +function del (self, hit) { + if (hit) { + if (self._dispose) self._dispose(hit.key, hit.value) + self._length -= hit.length + self._itemCount -- + delete self._cache[ hit.key ] + shiftLU(self, hit) + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, lu, length, now) { + this.key = key + this.value = value + this.lu = lu + this.length = length + this.now = now +} + +})() + +},{}],45:[function(require,module,exports){ +module.exports = sigmund +function sigmund (subject, maxSessions) { + maxSessions = maxSessions || 10; + var notes = []; + var analysis = ''; + var RE = RegExp; + + function psychoAnalyze (subject, session) { + if (session > maxSessions) return; + + if (typeof subject === 'function' || + typeof subject === 'undefined') { + return; + } + + if (typeof subject !== 'object' || !subject || + (subject instanceof RE)) { + analysis += subject; + return; + } + + if (notes.indexOf(subject) !== -1 || session === maxSessions) return; + + notes.push(subject); + analysis += '{'; + Object.keys(subject).forEach(function (issue, _, __) { + // pseudo-private values. skip those. + if (issue.charAt(0) === '_') return; + var to = typeof subject[issue]; + if (to === 'function' || to === 'undefined') return; + analysis += issue; + psychoAnalyze(subject[issue], session + 1); + }); + } + psychoAnalyze(subject, 0); + return analysis; +} + +// vim: set softtabstop=4 shiftwidth=4: + +},{}],46:[function(require,module,exports){ (function (Buffer){ function FilerBuffer (subject, encoding, nonZero) { @@ -6634,7 +8235,7 @@ Object.keys(Buffer).forEach(function (p) { module.exports = FilerBuffer; }).call(this,require("buffer").Buffer) -},{"buffer":38}],43:[function(require,module,exports){ +},{"buffer":38}],47:[function(require,module,exports){ var O_READ = 'READ'; var O_WRITE = 'WRITE'; var O_CREATE = 'CREATE'; @@ -6716,7 +8317,7 @@ module.exports = { } }; -},{}],44:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ var MODE_FILE = require('./constants.js').MODE_FILE; module.exports = function DirectoryEntry(id, type) { @@ -6724,7 +8325,7 @@ module.exports = function DirectoryEntry(id, type) { this.type = type || MODE_FILE; }; -},{"./constants.js":43}],45:[function(require,module,exports){ +},{"./constants.js":47}],49:[function(require,module,exports){ (function (Buffer){ // Adapt encodings to work with Buffer or Uint8Array, they expect the latter function decode(buf) { @@ -6741,7 +8342,7 @@ module.exports = { }; }).call(this,require("buffer").Buffer) -},{"buffer":38}],46:[function(require,module,exports){ +},{"buffer":38}],50:[function(require,module,exports){ var errors = {}; [ /** @@ -6847,7 +8448,7 @@ var errors = {}; module.exports = errors; -},{}],47:[function(require,module,exports){ +},{}],51:[function(require,module,exports){ var _ = require('../../lib/nodash.js'); var Path = require('../path.js'); @@ -7663,6 +9264,8 @@ function read_data(context, ofd, buffer, offset, length, position, callback) { function read_file_data(error, result) { if(error) { callback(error); + } else if(result.mode === 'DIRECTORY') { + callback(new Errors.EISDIR('the named file is a directory', ofd.path)); } else { fileNode = result; context.getBuffer(fileNode.data, handle_file_data); @@ -8920,7 +10523,7 @@ module.exports = { ftruncate: ftruncate }; -},{"../../lib/nodash.js":4,"../buffer.js":42,"../constants.js":43,"../directory-entry.js":44,"../encoding.js":45,"../errors.js":46,"../node.js":51,"../open-file-description.js":52,"../path.js":53,"../stats.js":61,"../super-node.js":62}],48:[function(require,module,exports){ +},{"../../lib/nodash.js":4,"../buffer.js":46,"../constants.js":47,"../directory-entry.js":48,"../encoding.js":49,"../errors.js":50,"../node.js":55,"../open-file-description.js":56,"../path.js":57,"../stats.js":65,"../super-node.js":66}],52:[function(require,module,exports){ var _ = require('../../lib/nodash.js'); var isNullPath = require('../path.js').isNull; @@ -9010,6 +10613,9 @@ function FileSystem(options, callback) { fs.stdout = STDOUT; fs.stderr = STDERR; + // Expose Shell constructor + this.Shell = Shell.bind(undefined, this); + // Safely expose the list of open files and file // descriptor management functions var openFiles = {}; @@ -9257,13 +10863,9 @@ FileSystem.providers = providers; }; }); -FileSystem.prototype.Shell = function(options) { - return new Shell(this, options); -}; - module.exports = FileSystem; -},{"../../lib/intercom.js":3,"../../lib/nodash.js":4,"../constants.js":43,"../errors.js":46,"../fs-watcher.js":49,"../path.js":53,"../providers/index.js":54,"../shared.js":58,"../shell/shell.js":60,"./implementation.js":47}],49:[function(require,module,exports){ +},{"../../lib/intercom.js":3,"../../lib/nodash.js":4,"../constants.js":47,"../errors.js":50,"../fs-watcher.js":53,"../path.js":57,"../providers/index.js":58,"../shared.js":62,"../shell/shell.js":64,"./implementation.js":51}],53:[function(require,module,exports){ var EventEmitter = require('../lib/eventemitter.js'); var Path = require('./path.js'); var Intercom = require('../lib/intercom.js'); @@ -9327,15 +10929,16 @@ FSWatcher.prototype.constructor = FSWatcher; module.exports = FSWatcher; -},{"../lib/eventemitter.js":2,"../lib/intercom.js":3,"./path.js":53}],50:[function(require,module,exports){ +},{"../lib/eventemitter.js":2,"../lib/intercom.js":3,"./path.js":57}],54:[function(require,module,exports){ module.exports = { FileSystem: require('./filesystem/interface.js'), Buffer: require('./buffer.js'), Path: require('./path.js'), - Errors: require('./errors.js') + Errors: require('./errors.js'), + Shell: require('./shell/shell.js') }; -},{"./buffer.js":42,"./errors.js":46,"./filesystem/interface.js":48,"./path.js":53}],51:[function(require,module,exports){ +},{"./buffer.js":46,"./errors.js":50,"./filesystem/interface.js":52,"./path.js":57,"./shell/shell.js":64}],55:[function(require,module,exports){ var MODE_FILE = require('./constants.js').MODE_FILE; function Node(options) { @@ -9390,7 +10993,7 @@ Node.create = function(options, callback) { module.exports = Node; -},{"./constants.js":43}],52:[function(require,module,exports){ +},{"./constants.js":47}],56:[function(require,module,exports){ var Errors = require('./errors.js'); function OpenFileDescription(path, id, flags, position) { @@ -9423,7 +11026,7 @@ OpenFileDescription.prototype.getNode = function(context, callback) { module.exports = OpenFileDescription; -},{"./errors.js":46}],53:[function(require,module,exports){ +},{"./errors.js":50}],57:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -9492,7 +11095,7 @@ function resolve() { resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - // XXXidbfs: we don't have process.cwd() so we use '/' as a fallback + // XXXfiler: we don't have process.cwd() so we use '/' as a fallback var path = (i >= 0) ? arguments[i] : '/'; // Skip empty and invalid entries @@ -9610,7 +11213,7 @@ function basename(path, ext) { if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } - // XXXidbfs: node.js just does `return f` + // XXXfiler: node.js just does `return f` return f === "" ? "/" : f; } @@ -9632,7 +11235,19 @@ function isNull(path) { return false; } -// XXXidbfs: we don't support path.exists() or path.existsSync(), which +// Make sure we don't double-add a trailing slash (e.g., '/' -> '//') +function addTrailing(path) { + return path.replace(/\/*$/, '/'); +} + +// Deal with multiple slashes at the end, one, or none +// and make sure we don't return the empty string. +function removeTrailing(path) { + path = path.replace(/\/*$/, ''); + return path === '' ? '/' : path; +} + +// XXXfiler: we don't support path.exists() or path.existsSync(), which // are deprecated, and need a FileSystem instance to work. Use fs.stat(). module.exports = { @@ -9646,10 +11261,13 @@ module.exports = { basename: basename, extname: extname, isAbsolute: isAbsolute, - isNull: isNull + isNull: isNull, + // Non-node but useful... + addTrailing: addTrailing, + removeTrailing: removeTrailing }; -},{}],54:[function(require,module,exports){ +},{}],58:[function(require,module,exports){ var IndexedDB = require('./indexeddb.js'); var WebSQL = require('./websql.js'); var Memory = require('./memory.js'); @@ -9686,7 +11304,7 @@ module.exports = { }()) }; -},{"./indexeddb.js":55,"./memory.js":56,"./websql.js":57}],55:[function(require,module,exports){ +},{"./indexeddb.js":59,"./memory.js":60,"./websql.js":61}],59:[function(require,module,exports){ (function (global,Buffer){ var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME; var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME; @@ -9838,7 +11456,7 @@ IndexedDB.prototype.getReadWriteContext = function() { module.exports = IndexedDB; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"../buffer.js":42,"../constants.js":43,"../errors.js":46,"buffer":38}],56:[function(require,module,exports){ +},{"../buffer.js":46,"../constants.js":47,"../errors.js":50,"buffer":38}],60:[function(require,module,exports){ var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME; // NOTE: prefer setImmediate to nextTick for proper recursion yielding. // see https://github.com/js-platform/filer/pull/24 @@ -9930,7 +11548,7 @@ Memory.prototype.getReadWriteContext = function() { module.exports = Memory; -},{"../../lib/async.js":1,"../constants.js":43}],57:[function(require,module,exports){ +},{"../../lib/async.js":1,"../constants.js":47}],61:[function(require,module,exports){ (function (global){ var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME; var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME; @@ -10105,7 +11723,7 @@ WebSQL.prototype.getReadWriteContext = function() { module.exports = WebSQL; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../buffer.js":42,"../constants.js":43,"../errors.js":46,"base64-arraybuffer":5}],58:[function(require,module,exports){ +},{"../buffer.js":46,"../constants.js":47,"../errors.js":50,"base64-arraybuffer":5}],62:[function(require,module,exports){ function guid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); @@ -10133,7 +11751,7 @@ module.exports = { nop: nop }; -},{}],59:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ var defaults = require('../constants.js').ENVIRONMENT; module.exports = function Environment(env) { @@ -10150,12 +11768,13 @@ module.exports = function Environment(env) { }; }; -},{"../constants.js":43}],60:[function(require,module,exports){ +},{"../constants.js":47}],64:[function(require,module,exports){ var Path = require('../path.js'); var Errors = require('../errors.js'); var Environment = require('./environment.js'); var async = require('../../lib/async.js'); var Encoding = require('../encoding.js'); +var minimatch = require('minimatch'); function Shell(fs, options) { options = options || {}; @@ -10579,9 +12198,125 @@ Shell.prototype.mkdirp = function(path, callback) { _mkdirp(path, callback); }; +/** + * Recursively walk a directory tree, reporting back all paths + * that were found along the way. The `path` must be a dir. + * Valid options include a `regex` for pattern matching paths + * and an `exec` function of the form `function(path, next)` where + * `path` is the current path that was found (dir paths have an '/' + * appended) and `next` is a callback to call when done processing + * the current path, passing any error object back as the first argument. + * `find` returns a flat array of absolute paths for all matching/found + * paths as the final argument to the callback. + */ + Shell.prototype.find = function(path, options, callback) { + var sh = this; + var fs = sh.fs; + if(typeof options === 'function') { + callback = options; + options = {}; + } + options = options || {}; + callback = callback || function(){}; + + var exec = options.exec || function(path, next) { next(); }; + var found = []; + + if(!path) { + callback(new Errors.EINVAL('Missing path argument')); + return; + } + + function processPath(path, callback) { + exec(path, function(err) { + if(err) { + callback(err); + return; + } + + found.push(path); + callback(); + }); + } + + function maybeProcessPath(path, callback) { + // Test the path against the user's regex, name, path primaries (if any) + // and remove any trailing slashes added previously. + var rawPath = Path.removeTrailing(path); + + // Check entire path against provided regex, if any + if(options.regex && !options.regex.test(rawPath)) { + callback(); + return; + } + + // Check basename for matches against name primary, if any + if(options.name && !minimatch(Path.basename(rawPath), options.name)) { + callback(); + return; + } + + // Check dirname for matches against path primary, if any + if(options.path && !minimatch(Path.dirname(rawPath), options.path)) { + callback(); + return; + } + + processPath(path, callback); + } + + function walk(path, callback) { + path = Path.resolve(sh.pwd(), path); + + // The path is either a file or dir, and instead of doing + // a stat() to determine it first, we just try to readdir() + // and it will either work or not, and we handle the non-dir error. + fs.readdir(path, function(err, entries) { + if(err) { + if(err.code === 'ENOTDIR' /* file case, ignore error */) { + maybeProcessPath(path, callback); + } else { + callback(err); + } + return; + } + + // Path is really a dir, add a trailing / and report it found + maybeProcessPath(Path.addTrailing(path), function(err) { + if(err) { + callback(err); + return; + } + + entries = entries.map(function(entry) { + return Path.join(path, entry); + }); + + async.eachSeries(entries, walk, function(err) { + callback(err, found); + }); + }); + }); + } + + // Make sure we are starting with a dir path + fs.stat(path, function(err, stats) { + if(err) { + callback(err); + return; + } + if(!stats.isDirectory()) { + callback(new Errors.ENOTDIR(null, path)); + return; + } + + walk(path, callback); + }); +}; + module.exports = Shell; -},{"../../lib/async.js":1,"../encoding.js":45,"../errors.js":46,"../path.js":53,"./environment.js":59}],61:[function(require,module,exports){ +},{"../../lib/async.js":1,"../encoding.js":49,"../errors.js":50,"../path.js":57,"./environment.js":63,"minimatch":43}],65:[function(require,module,exports){ var Constants = require('./constants.js'); function Stats(fileNode, devName) { @@ -10618,7 +12353,7 @@ function() { module.exports = Stats; -},{"./constants.js":43}],62:[function(require,module,exports){ +},{"./constants.js":47}],66:[function(require,module,exports){ var Constants = require('./constants.js'); function SuperNode(options) { @@ -10646,7 +12381,7 @@ SuperNode.create = function(options, callback) { module.exports = SuperNode; -},{"./constants.js":43}],63:[function(require,module,exports){ +},{"./constants.js":47}],67:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10684,7 +12419,7 @@ describe('trailing slashes in path names, issue 105', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],64:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],68:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10718,7 +12453,7 @@ describe('fs.writeFile truncation - issue 106', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],65:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],69:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10741,7 +12476,7 @@ describe('fs.writeFile and non-existing directory, issue 239', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],66:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],70:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10752,7 +12487,7 @@ describe('sh.cd doesn\'t seem to be working from a relative path if I am one or it('should properly deal with relative paths missing ./ and ../', function(done) { var fs = util.fs(); - var sh = fs.Shell(); + var sh = new fs.Shell(); sh.mkdirp('/home/scott', function(err) { if(err) throw err; @@ -10779,7 +12514,7 @@ describe('sh.cd doesn\'t seem to be working from a relative path if I am one or }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],67:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],71:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10823,7 +12558,7 @@ describe('Filer.Buffer static methods are in tact, issue 249', function() { }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],68:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],72:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10872,7 +12607,7 @@ describe('EISDIR when trying to open a dir path - issue 254', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],69:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],73:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10963,7 +12698,7 @@ describe('Queued operations should error when fs is in error state, issue 258', }); }); -},{"../..":50,"../../lib/async.js":1,"../lib/test-utils.js":76,"chai":6}],70:[function(require,module,exports){ +},{"../..":54,"../../lib/async.js":1,"../lib/test-utils.js":80,"chai":6}],74:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -10987,7 +12722,7 @@ describe('fs.readdir on non-dir paths, issue 267', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],71:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],75:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -11017,7 +12752,7 @@ describe('undefined and relative paths, issue270', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],72:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],76:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -11029,7 +12764,7 @@ describe('sh.ls and deep directory trees', function() { it('should not crash when calling sh.ls() on deep directory layouts', function(done) { var fs = util.fs(); - var sh = fs.Shell(); + var sh = new fs.Shell(); var path = ''; for(var i=0; i<50; i++) { @@ -11049,7 +12784,7 @@ describe('sh.ls and deep directory trees', function() { it('should not crash when calling sh.ls() on wide directory layouts', function(done) { var fs = util.fs(); - var sh = fs.Shell(); + var sh = new fs.Shell(); var dirName = '/dir'; @@ -11078,7 +12813,7 @@ describe('sh.ls and deep directory trees', function() { }); }); -},{"../..":50,"../../lib/async.js":1,"../lib/test-utils.js":76,"chai":6}],73:[function(require,module,exports){ +},{"../..":54,"../../lib/async.js":1,"../lib/test-utils.js":80,"chai":6}],77:[function(require,module,exports){ /** * Add your test spec files to the list in order to * get them running by default. @@ -11119,6 +12854,7 @@ require("./spec/times.spec"); require("./spec/time-flags.spec"); require("./spec/fs.watch.spec"); require("./spec/errors.spec"); +require("./spec/fs.shell.spec"); // Filer.FileSystem.providers.* require("./spec/providers/providers.spec"); @@ -11135,6 +12871,7 @@ require("./spec/shell/ls.spec"); require("./spec/shell/rm.spec"); require("./spec/shell/env.spec"); require("./spec/shell/mkdirp.spec"); +require("./spec/shell/find.spec"); // Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test) require("./spec/node-js/simple/test-fs-mkdir"); @@ -11155,7 +12892,7 @@ require("./bugs/issue258.js"); require("./bugs/issue267.js"); require("./bugs/issue270.js"); -},{"./bugs/issue105":63,"./bugs/issue106":64,"./bugs/issue239":65,"./bugs/issue247.js":66,"./bugs/issue249":67,"./bugs/issue254.js":68,"./bugs/issue258.js":69,"./bugs/issue267.js":70,"./bugs/issue270.js":71,"./bugs/ls-depth-bug":72,"./spec/errors.spec":78,"./spec/filer.filesystem.spec":79,"./spec/filer.spec":80,"./spec/fs.appendFile.spec":81,"./spec/fs.close.spec":82,"./spec/fs.exists.spec":83,"./spec/fs.link.spec":84,"./spec/fs.lseek.spec":85,"./spec/fs.lstat.spec":86,"./spec/fs.mkdir.spec":87,"./spec/fs.mknod.spec":88,"./spec/fs.open.spec":89,"./spec/fs.read.spec":90,"./spec/fs.readdir.spec":91,"./spec/fs.readlink.spec":92,"./spec/fs.rename.spec":93,"./spec/fs.rmdir.spec":94,"./spec/fs.spec":95,"./spec/fs.stat.spec":96,"./spec/fs.stats.spec":97,"./spec/fs.symlink.spec":98,"./spec/fs.truncate.spec":99,"./spec/fs.unlink.spec":100,"./spec/fs.utimes.spec":101,"./spec/fs.watch.spec":102,"./spec/fs.write.spec":103,"./spec/fs.writeFile-readFile.spec":104,"./spec/fs.xattr.spec":105,"./spec/node-js/simple/test-fs-mkdir":106,"./spec/node-js/simple/test-fs-null-bytes":107,"./spec/node-js/simple/test-fs-watch":109,"./spec/node-js/simple/test-fs-watch-recursive":108,"./spec/path-resolution.spec":110,"./spec/providers/providers.indexeddb.spec":112,"./spec/providers/providers.memory.spec":113,"./spec/providers/providers.spec":114,"./spec/providers/providers.websql.spec":115,"./spec/shell/cat.spec":116,"./spec/shell/cd.spec":117,"./spec/shell/env.spec":118,"./spec/shell/exec.spec":119,"./spec/shell/ls.spec":120,"./spec/shell/mkdirp.spec":121,"./spec/shell/rm.spec":122,"./spec/shell/touch.spec":123,"./spec/time-flags.spec":124,"./spec/times.spec":125,"./spec/trailing-slashes.spec":126}],74:[function(require,module,exports){ +},{"./bugs/issue105":67,"./bugs/issue106":68,"./bugs/issue239":69,"./bugs/issue247.js":70,"./bugs/issue249":71,"./bugs/issue254.js":72,"./bugs/issue258.js":73,"./bugs/issue267.js":74,"./bugs/issue270.js":75,"./bugs/ls-depth-bug":76,"./spec/errors.spec":82,"./spec/filer.filesystem.spec":83,"./spec/filer.spec":84,"./spec/fs.appendFile.spec":85,"./spec/fs.close.spec":86,"./spec/fs.exists.spec":87,"./spec/fs.link.spec":88,"./spec/fs.lseek.spec":89,"./spec/fs.lstat.spec":90,"./spec/fs.mkdir.spec":91,"./spec/fs.mknod.spec":92,"./spec/fs.open.spec":93,"./spec/fs.read.spec":94,"./spec/fs.readdir.spec":95,"./spec/fs.readlink.spec":96,"./spec/fs.rename.spec":97,"./spec/fs.rmdir.spec":98,"./spec/fs.shell.spec":99,"./spec/fs.spec":100,"./spec/fs.stat.spec":101,"./spec/fs.stats.spec":102,"./spec/fs.symlink.spec":103,"./spec/fs.truncate.spec":104,"./spec/fs.unlink.spec":105,"./spec/fs.utimes.spec":106,"./spec/fs.watch.spec":107,"./spec/fs.write.spec":108,"./spec/fs.writeFile-readFile.spec":109,"./spec/fs.xattr.spec":110,"./spec/node-js/simple/test-fs-mkdir":111,"./spec/node-js/simple/test-fs-null-bytes":112,"./spec/node-js/simple/test-fs-watch":114,"./spec/node-js/simple/test-fs-watch-recursive":113,"./spec/path-resolution.spec":115,"./spec/providers/providers.indexeddb.spec":117,"./spec/providers/providers.memory.spec":118,"./spec/providers/providers.spec":119,"./spec/providers/providers.websql.spec":120,"./spec/shell/cat.spec":121,"./spec/shell/cd.spec":122,"./spec/shell/env.spec":123,"./spec/shell/exec.spec":124,"./spec/shell/find.spec":125,"./spec/shell/ls.spec":126,"./spec/shell/mkdirp.spec":127,"./spec/shell/rm.spec":128,"./spec/shell/touch.spec":129,"./spec/time-flags.spec":130,"./spec/times.spec":131,"./spec/trailing-slashes.spec":132}],78:[function(require,module,exports){ (function (global){ var Filer = require("../.."); @@ -11176,6 +12913,8 @@ function IndexedDBTestProvider(name) { var that = this; function cleanup(callback) { + callback = callback || function(){}; + if(!that.provider || _done) { return callback(); } @@ -11186,7 +12925,6 @@ function IndexedDBTestProvider(name) { that.provider.db.close(); } - callback = callback || function(){}; var request = indexedDB.deleteDatabase(name); function finished() { that.provider = null; @@ -11215,13 +12953,15 @@ IndexedDBTestProvider.isSupported = function() { module.exports = IndexedDBTestProvider; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../..":50}],75:[function(require,module,exports){ +},{"../..":54}],79:[function(require,module,exports){ var Filer = require('../..'); function MemoryTestProvider(name) { var that = this; function cleanup(callback) { + callback = callback || function(){}; + that.provider = null; callback(); } @@ -11242,7 +12982,7 @@ MemoryTestProvider.isSupported = function() { module.exports = MemoryTestProvider; -},{"../..":50}],76:[function(require,module,exports){ +},{"../..":54}],80:[function(require,module,exports){ (function(global) { var Filer = require('../..'); @@ -11330,7 +13070,8 @@ module.exports = MemoryTestProvider; } function shell(options) { - return fs().Shell(options); + var _fs = fs(); + return new _fs.Shell(options); } function cleanup(callback) { @@ -11378,7 +13119,7 @@ module.exports = MemoryTestProvider; }(this)); -},{"../..":50,"./indexeddb.js":74,"./memory.js":75,"./websql.js":77}],77:[function(require,module,exports){ +},{"../..":54,"./indexeddb.js":78,"./memory.js":79,"./websql.js":81}],81:[function(require,module,exports){ (function (global){ var Filer = require('../..'); @@ -11394,9 +13135,12 @@ function WebSQLTestProvider(name) { var that = this; function cleanup(callback) { + callback = callback || function(){}; + if(!that.provider || _done) { return callback(); } + // Provider is there, but db was never touched if(!that.provider.db) { return callback(); @@ -11428,7 +13172,7 @@ WebSQLTestProvider.isSupported = function() { module.exports = WebSQLTestProvider; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../..":50}],78:[function(require,module,exports){ +},{"../..":54}],82:[function(require,module,exports){ var Filer = require('../..'); var expect = require('chai').expect; @@ -11611,7 +13355,7 @@ describe("Filer.Errors", function() { }); }); -},{"../..":50,"chai":6}],79:[function(require,module,exports){ +},{"../..":54,"chai":6}],83:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -11659,7 +13403,7 @@ describe("Filer.FileSystem", function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],80:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],84:[function(require,module,exports){ var Filer = require('../..'); var expect = require('chai').expect; @@ -11671,9 +13415,13 @@ describe("Filer", function() { it("has FileSystem constructor", function() { expect(typeof Filer.FileSystem).to.equal('function'); }); + + it("has Shell constructor", function() { + expect(typeof Filer.Shell).to.equal('function'); + }); }); -},{"../..":50,"chai":6}],81:[function(require,module,exports){ +},{"../..":54,"chai":6}],85:[function(require,module,exports){ (function (Buffer){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); @@ -11807,7 +13555,7 @@ describe('fs.appendFile', function() { }); }).call(this,require("buffer").Buffer) -},{"../..":50,"../lib/test-utils.js":76,"buffer":38,"chai":6}],82:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"buffer":38,"chai":6}],86:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -11839,7 +13587,7 @@ describe('fs.close', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],83:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],87:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -11901,7 +13649,7 @@ describe('fs.exists', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],84:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],88:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -11975,7 +13723,7 @@ describe('fs.link', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],85:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],89:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12144,7 +13892,7 @@ describe('fs.lseek', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],86:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],90:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12197,7 +13945,7 @@ describe('fs.lstat', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],87:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],91:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12248,7 +13996,7 @@ describe('fs.mkdir', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],88:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],92:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12331,7 +14079,7 @@ describe('fs.mknod', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],89:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],93:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12473,7 +14221,7 @@ describe('fs.open', function() { }); }); -},{"../..":50,"../../src/constants.js":43,"../lib/test-utils.js":76,"chai":6}],90:[function(require,module,exports){ +},{"../..":54,"../../src/constants.js":47,"../lib/test-utils.js":80,"chai":6}],94:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12537,9 +14285,33 @@ describe('fs.read', function() { }); }); }); + + it('should fail to read a directory', function(done) { + var fs = util.fs(); + var buf = new Filer.Buffer(20); + var buf2 = new Filer.Buffer(20); + buf.fill(0); + buf2.fill(0); + + fs.mkdir('/mydir', function(error) { + if(error) throw err; + + fs.open('/mydir', 'r', function(error, fd) { + if(error) throw error; + + fs.read(fd, buf, 0, buf.length, 0, function(error, result) { + expect(error).to.exist; + expect(error.code).to.equal('EISDIR'); + expect(result).to.equal(0); + expect(buf).to.deep.equal(buf2); + done(); + }); + }); + }); + }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],91:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],95:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12599,7 +14371,7 @@ describe('fs.readdir', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],92:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],96:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12648,7 +14420,7 @@ describe('fs.readlink', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],93:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],97:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12700,7 +14472,7 @@ describe('fs.rename', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],94:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],98:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12803,7 +14575,42 @@ describe('fs.rmdir', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],95:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],99:[function(require,module,exports){ +var Filer = require('../..'); +var util = require('../lib/test-utils.js'); +var expect = require('chai').expect; + +describe("fs.Shell", function() { + beforeEach(util.setup); + afterEach(util.cleanup); + + it("is a function", function(done) { + var fs = util.fs(); + expect(typeof fs.Shell).to.equal('function'); + + done(); + }); + + it('should return a FileSystemShell instance', function(done) { + var fs = util.fs(); + var sh = new fs.Shell(); + + expect(sh.prototype).to.deep.equal((new Filer.Shell(fs)).prototype); + done(); + }); + + it('should reflect changes to the prototype', function(done){ + var fs = util.fs(); + var sh = new fs.Shell(); + + Filer.Shell.prototype.test = "foo"; + + expect(sh.test).to.equal("foo"); + done(); + }); +}); + +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],100:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12829,7 +14636,7 @@ describe("fs", function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],96:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],101:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -12926,7 +14733,7 @@ describe('fs.stat', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],97:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],102:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -13176,7 +14983,7 @@ describe('fs.stats', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],98:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],103:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -13225,7 +15032,7 @@ describe('fs.symlink', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],99:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],104:[function(require,module,exports){ (function (Buffer){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); @@ -13419,7 +15226,7 @@ describe('fs.truncate', function() { }); }).call(this,require("buffer").Buffer) -},{"../..":50,"../lib/test-utils.js":76,"buffer":38,"chai":6}],100:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"buffer":38,"chai":6}],105:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -13526,7 +15333,7 @@ describe('fs.unlink', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],101:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],106:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -13708,7 +15515,7 @@ describe('fs.utimes', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],102:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],107:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -13778,7 +15585,7 @@ describe('fs.watch', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],103:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],108:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -13842,7 +15649,7 @@ describe('fs.write', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],104:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],109:[function(require,module,exports){ (function (Buffer){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); @@ -13950,7 +15757,7 @@ describe('fs.writeFile, fs.readFile', function() { }); }).call(this,require("buffer").Buffer) -},{"../..":50,"../lib/test-utils.js":76,"buffer":38,"chai":6}],105:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"buffer":38,"chai":6}],110:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -14346,7 +16153,7 @@ describe('fs.xattr', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],106:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],111:[function(require,module,exports){ var Filer = require('../../../..'); var util = require('../../../lib/test-utils.js'); var expect = require('chai').expect; @@ -14388,7 +16195,7 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/ }); }); -},{"../../../..":50,"../../../lib/test-utils.js":76,"chai":6}],107:[function(require,module,exports){ +},{"../../../..":54,"../../../lib/test-utils.js":80,"chai":6}],112:[function(require,module,exports){ var Filer = require('../../../..'); var util = require('../../../lib/test-utils.js'); var expect = require('chai').expect; @@ -14452,7 +16259,7 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/ }); }); -},{"../../../..":50,"../../../lib/test-utils.js":76,"chai":6}],108:[function(require,module,exports){ +},{"../../../..":54,"../../../lib/test-utils.js":80,"chai":6}],113:[function(require,module,exports){ var Filer = require('../../../..'); var util = require('../../../lib/test-utils.js'); var expect = require('chai').expect; @@ -14490,7 +16297,7 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/ }); }); -},{"../../../..":50,"../../../lib/test-utils.js":76,"chai":6}],109:[function(require,module,exports){ +},{"../../../..":54,"../../../lib/test-utils.js":80,"chai":6}],114:[function(require,module,exports){ var Filer = require('../../../..'); var util = require('../../../lib/test-utils.js'); var expect = require('chai').expect; @@ -14565,7 +16372,7 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/ }); }); -},{"../../../..":50,"../../../lib/test-utils.js":76,"chai":6}],110:[function(require,module,exports){ +},{"../../../..":54,"../../../lib/test-utils.js":80,"chai":6}],115:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -14791,9 +16598,27 @@ describe('path resolution', function() { }); }); }); + + it('should properly add trailing slashes with Path.addTrailing()', function() { + var Path = Filer.Path; + expect(Path.addTrailing('/')).to.equal('/'); + expect(Path.addTrailing('/////')).to.equal('/'); + expect(Path.addTrailing('.')).to.equal('./'); + expect(Path.addTrailing('/dir')).to.equal('/dir/'); + expect(Path.addTrailing('/dir/')).to.equal('/dir/'); + }); + + it('should properly remove trailing slashes with Path.removeTrailing()', function() { + var Path = Filer.Path; + expect(Path.removeTrailing('/')).to.equal('/'); + expect(Path.removeTrailing('/////')).to.equal('/'); + expect(Path.removeTrailing('./')).to.equal('.'); + expect(Path.removeTrailing('/dir/')).to.equal('/dir'); + expect(Path.removeTrailing('/dir//')).to.equal('/dir'); + }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],111:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],116:[function(require,module,exports){ var Buffer = require('../../..').Buffer; var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -14960,19 +16785,19 @@ module.exports = function createProviderTestsFor(providerName, testProvider) { }); }; -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],112:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],117:[function(require,module,exports){ var util = require('../../lib/test-utils.js'); var providerBase = require('./providers.base.js'); providerBase('IndexedDB', util.providers.IndexedDB); -},{"../../lib/test-utils.js":76,"./providers.base.js":111}],113:[function(require,module,exports){ +},{"../../lib/test-utils.js":80,"./providers.base.js":116}],118:[function(require,module,exports){ var util = require('../../lib/test-utils.js'); var providerBase = require('./providers.base.js'); providerBase('Memory', util.providers.Memory); -},{"../../lib/test-utils.js":76,"./providers.base.js":111}],114:[function(require,module,exports){ +},{"../../lib/test-utils.js":80,"./providers.base.js":116}],119:[function(require,module,exports){ var Filer = require('../../..'); var expect = require('chai').expect; @@ -15002,13 +16827,13 @@ describe("Filer.FileSystem.providers", function() { }); }); -},{"../../..":50,"chai":6}],115:[function(require,module,exports){ +},{"../../..":54,"chai":6}],120:[function(require,module,exports){ var util = require('../../lib/test-utils.js'); var providerBase = require('./providers.base.js'); providerBase('WebSQL', util.providers.WebSQL); -},{"../../lib/test-utils.js":76,"./providers.base.js":111}],116:[function(require,module,exports){ +},{"../../lib/test-utils.js":80,"./providers.base.js":116}],121:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15024,7 +16849,7 @@ describe('FileSystemShell.cat', function() { it('should fail when files argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cat(null, function(error, data) { expect(error).to.exist; @@ -15036,7 +16861,7 @@ describe('FileSystemShell.cat', function() { it('should return the contents of a single file', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "file contents"; fs.writeFile('/file', contents, function(err) { @@ -15052,7 +16877,7 @@ describe('FileSystemShell.cat', function() { it('should return the contents of multiple files', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "file contents"; var contents2 = contents + '\n' + contents; @@ -15073,7 +16898,7 @@ describe('FileSystemShell.cat', function() { it('should fail if any of multiple file paths is invalid', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "file contents"; var contents2 = contents + '\n' + contents; @@ -15094,7 +16919,7 @@ describe('FileSystemShell.cat', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],117:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],122:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15115,7 +16940,7 @@ describe('FileSystemShell.cd', function() { it('should allow changing the path to a valid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15131,7 +16956,7 @@ describe('FileSystemShell.cd', function() { it('should fail when changing the path to an invalid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15148,7 +16973,7 @@ describe('FileSystemShell.cd', function() { it('should fail when changing the path to a file', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.writeFile('/file', 'file', function(err) { if(err) throw err; @@ -15165,7 +16990,7 @@ describe('FileSystemShell.cd', function() { it('should allow relative paths for a valid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15181,7 +17006,7 @@ describe('FileSystemShell.cd', function() { it('should allow .. in paths for a valid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15208,7 +17033,7 @@ describe('FileSystemShell.cd', function() { fs.symlink('/dir', '/link', function(error) { if(error) throw error; - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cd('link', function(error) { expect(error).not.to.exist; expect(shell.pwd()).to.equal('/link'); @@ -15219,7 +17044,7 @@ describe('FileSystemShell.cd', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],118:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],123:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15256,7 +17081,7 @@ describe('FileSystemShell.env', function() { it('should fail when dirs argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cat(null, function(error, list) { expect(error).to.exist; @@ -15268,7 +17093,7 @@ describe('FileSystemShell.env', function() { it('should give new value for shell.pwd() when cwd changes', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15284,7 +17109,7 @@ describe('FileSystemShell.env', function() { it('should create/return the default tmp dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); expect(shell.env.get('TMP')).to.equal('/tmp'); shell.tempDir(function(err, tmp) { @@ -15299,7 +17124,7 @@ describe('FileSystemShell.env', function() { it('should create/return the tmp dir specified in env.TMP', function(done) { var fs = util.fs(); - var shell = fs.Shell({ + var shell = new fs.Shell({ env: { TMP: '/tempdir' } @@ -15318,7 +17143,7 @@ describe('FileSystemShell.env', function() { it('should allow repeated calls to tempDir()', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); expect(shell.env.get('TMP')).to.equal('/tmp'); shell.tempDir(function(err, tmp) { @@ -15334,7 +17159,7 @@ describe('FileSystemShell.env', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],119:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],124:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15350,7 +17175,7 @@ describe('FileSystemShell.exec', function() { it('should be able to execute a command .js file from the filesystem', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var cmdString = "fs.writeFile(args[0], args[1], callback);"; fs.writeFile('/cmd.js', cmdString, function(error) { @@ -15369,7 +17194,215 @@ describe('FileSystemShell.exec', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],120:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],125:[function(require,module,exports){ +var Filer = require('../../..'); +var util = require('../../lib/test-utils.js'); +var expect = require('chai').expect; + +describe('FileSystemShell.find', function() { + beforeEach(function(done) { + util.setup(function() { + var fs = util.fs(); + /** + * Create a basic fs layout for each test: + * + * / + * --file1 + * --file2 + * --dir1/ + * --file3 + * --subdir1/ + * --dir2/ + * --file4 + */ + fs.writeFile('/file1', 'file1', function(err) { + if(err) throw err; + + fs.writeFile('/file2', 'file2', function(err) { + if(err) throw err; + + fs.mkdir('/dir1', function(err) { + if(err) throw err; + + fs.writeFile('/dir1/file3', 'file3', function(err) { + if(err) throw err; + + fs.mkdir('/dir1/subdir1', function(err) { + if(err) throw err; + + fs.mkdir('/dir2', function(err) { + if(err) throw err; + + fs.writeFile('/dir2/file4', 'file4', function(err) { + if(err) throw err; + + done(); + }); + }); + }); + }); + }); + }); + }); + }); + }); + afterEach(util.cleanup); + + it('should be a function', function() { + var shell = util.shell(); + expect(shell.find).to.be.a('function'); + }); + + it('should fail when path does not exist', function(done) { + var shell = util.shell(); + + shell.find('/no-such-folder', function(err, found) { + expect(err).to.exist; + expect(err.code).to.equal('ENOENT'); + expect(found).not.to.exist; + done(); + }); + }); + + it('should fail when path exists but is non-dir', function(done) { + var shell = util.shell(); + + shell.find('/file1', function(err, found) { + expect(err).to.exist; + expect(err.code).to.equal('ENOTDIR'); + expect(found).not.to.exist; + done(); + }); + }); + + it('should find all paths in the filesystem with no options', function(done) { + var shell = util.shell(); + + shell.find('/', function(err, found) { + expect(err).not.to.exist; + + var expected = [ + '/', + '/file1', + '/file2', + '/dir1/', + '/dir1/file3', + '/dir1/subdir1/', + '/dir2/', + '/dir2/file4' + ]; + expect(found).to.deep.equal(expected); + done(); + }); + }); + + it('should get same paths in exec as are found when complete', function(done) { + var shell = util.shell(); + var pathsSeen = []; + + function processPath(path, next) { + pathsSeen.push(path); + next(); + } + + shell.find('/', {exec: processPath}, function(err, found) { + expect(err).not.to.exist; + + expect(found).to.deep.equal(pathsSeen); + done(); + }); + }); + + it('should return only paths that match a regex pattern', function(done) { + var shell = util.shell(); + + shell.find('/', {regex: /file\d$/}, function(err, found) { + expect(err).not.to.exist; + + var expected = [ + '/file1', + '/file2', + '/dir1/file3', + '/dir2/file4' + ]; + expect(found).to.deep.equal(expected); + done(); + }); + }); + + it('should append a / to the end of a dir path', function(done) { + var shell = util.shell(); + var dirsSeen = 0; + + function endsWith(str, suffix) { + var lastIndex = str.lastIndexOf(suffix); + return (lastIndex !== -1) && (lastIndex + suffix.length === str.length); + } + + function processPath(path, next) { + expect(endsWith(path, '/')).to.be.true; + dirsSeen++; + next(); + } + + shell.find('/', {regex: /dir\d$/, exec: processPath}, function(err) { + expect(err).not.to.exist; + expect(dirsSeen).to.equal(3); + done(); + }); + }); + + it('should only look below the specified dir path', function(done) { + var shell = util.shell(); + + shell.find('/dir1', function(err, found) { + expect(err).not.to.exist; + + var expected = [ + '/dir1/', + '/dir1/file3', + '/dir1/subdir1/' + ]; + expect(found).to.deep.equal(expected); + done(); + }); + }); + + it('should allow using options.name to match basename with a pattern', function(done) { + var shell = util.shell(); + + shell.find('/', {name: 'file*'}, function(err, found) { + expect(err).not.to.exist; + + var expected = [ + '/file1', + '/file2', + '/dir1/file3', + '/dir2/file4' + ]; + expect(found).to.deep.equal(expected); + done(); + }); + }); + + it('should allow using options.path to match dirname with a pattern', function(done) { + var shell = util.shell(); + + shell.find('/', {name: '*ir1*'}, function(err, found) { + expect(err).not.to.exist; + + var expected = [ + '/dir1/', + '/dir1/subdir1/' + ]; + expect(found).to.deep.equal(expected); + done(); + }); + }); + +}); + +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],126:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15385,7 +17418,7 @@ describe('FileSystemShell.ls', function() { it('should fail when dirs argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cat(null, function(error, list) { expect(error).to.exist; @@ -15397,7 +17430,7 @@ describe('FileSystemShell.ls', function() { it('should return the contents of a simple dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; var contents2 = "bb"; @@ -15435,7 +17468,7 @@ describe('FileSystemShell.ls', function() { it('should return the shallow contents of a dir tree', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.mkdir('/dir', function(err) { @@ -15491,7 +17524,7 @@ describe('FileSystemShell.ls', function() { it('should return the deep contents of a dir tree', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.mkdir('/dir', function(err) { @@ -15558,7 +17591,7 @@ describe('FileSystemShell.ls', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],121:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],127:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15574,7 +17607,7 @@ describe('FileSystemShell.mkdirp', function() { it('should fail without a path provided', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp(null, function(err) { expect(err).to.exist; @@ -15585,7 +17618,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed if provided path is root', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp('/', function(err) { expect(err).to.not.exist; done(); @@ -15594,7 +17627,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed if the directory exists', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/test', function(err){ expect(err).to.not.exist; shell.mkdirp('/test',function(err) { @@ -15606,7 +17639,7 @@ describe('FileSystemShell.mkdirp', function() { it('fail if a file name is provided', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.writeFile('/test.txt', 'test', function(err){ expect(err).to.not.exist; shell.mkdirp('/test.txt', function(err) { @@ -15619,7 +17652,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed on a folder on root (\'/test\')', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp('/test', function(err) { expect(err).to.not.exist; fs.exists('/test', function(dir){ @@ -15631,7 +17664,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed on a folder with a nonexistant parent (\'/test/test\')', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp('/test/test', function(err) { expect(err).to.not.exist; fs.exists('/test', function(dir1){ @@ -15646,7 +17679,7 @@ describe('FileSystemShell.mkdirp', function() { it('should fail on a folder with a file for its parent (\'/test.txt/test\')', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.writeFile('/test.txt', 'test', function(err){ expect(err).to.not.exist; shell.mkdirp('/test.txt/test', function(err) { @@ -15658,7 +17691,7 @@ describe('FileSystemShell.mkdirp', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],122:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],128:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15674,7 +17707,7 @@ describe('FileSystemShell.rm', function() { it('should fail when path argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.rm(null, function(error, list) { expect(error).to.exist; @@ -15686,7 +17719,7 @@ describe('FileSystemShell.rm', function() { it('should remove a single file', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.writeFile('/file', contents, function(err) { @@ -15706,7 +17739,7 @@ describe('FileSystemShell.rm', function() { it('should remove an empty dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15725,7 +17758,7 @@ describe('FileSystemShell.rm', function() { it('should fail to remove a non-empty dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15744,7 +17777,7 @@ describe('FileSystemShell.rm', function() { it('should remove a non-empty dir with option.recursive set', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -15767,7 +17800,7 @@ describe('FileSystemShell.rm', function() { it('should work on a complex dir structure', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.mkdir('/dir', function(err) { @@ -15798,7 +17831,7 @@ describe('FileSystemShell.rm', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],123:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],129:[function(require,module,exports){ var Filer = require('../../..'); var util = require('../../lib/test-utils.js'); var expect = require('chai').expect; @@ -15821,7 +17854,7 @@ describe('FileSystemShell.touch', function() { it('should create a new file if path does not exist', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.touch('/newfile', function(error) { if(error) throw error; @@ -15836,7 +17869,7 @@ describe('FileSystemShell.touch', function() { it('should skip creating a new file if options.updateOnly is true', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.touch('/newfile', { updateOnly: true }, function(error) { if(error) throw error; @@ -15850,7 +17883,7 @@ describe('FileSystemShell.touch', function() { it('should update times if path does exist', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var atime = Date.parse('1 Oct 2000 15:33:22'); var mtime = Date.parse('30 Sep 2000 06:43:54'); @@ -15881,7 +17914,7 @@ describe('FileSystemShell.touch', function() { it('should update times to specified date if path does exist', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var date = Date.parse('1 Oct 2001 15:33:22'); fs.open('/newfile', 'w', function (error, fd) { @@ -15903,7 +17936,7 @@ describe('FileSystemShell.touch', function() { }); }); -},{"../../..":50,"../../lib/test-utils.js":76,"chai":6}],124:[function(require,module,exports){ +},{"../../..":54,"../../lib/test-utils.js":80,"chai":6}],130:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -16011,7 +18044,7 @@ describe('node times (atime, mtime, ctime) with mount flags', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],125:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],131:[function(require,module,exports){ var Filer = require('../..'); var util = require('../lib/test-utils.js'); var expect = require('chai').expect; @@ -16636,7 +18669,7 @@ describe('node times (atime, mtime, ctime)', function() { }); }); -},{"../..":50,"../lib/test-utils.js":76,"chai":6}],126:[function(require,module,exports){ +},{"../..":54,"../lib/test-utils.js":80,"chai":6}],132:[function(require,module,exports){ var Path = require('../..').Path; var expect = require('chai').expect; @@ -16653,4 +18686,4 @@ describe('Path.normalize and trailing slashes', function() { }); -},{"../..":50,"chai":6}]},{},[73]); \ No newline at end of file +},{"../..":54,"chai":6}]},{},[77]); \ No newline at end of file