Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

azuki-trusty / azk   deb

Repository URL to install this package:

Version: 0.5.1 

/ usr / lib / azk / node_modules / q-io / fs-mock.js


var Q = require("q");
var Boot = require("./fs-boot");
var Common = require("./fs-common");
var BufferStream = require("./buffer-stream");
var Reader = require("./reader");
var Set = require("collections/set");

module.exports = MockFs;

function MockFs(files, workingDirectory) {
    if (!(this instanceof MockFs)) {
        return new MockFs(files, workingDirectory);
    }
    this._root = new DirectoryNode(this, "/");

    function init() {
        // construct a file tree
    }

    Common.update(this, function () {
        return workingDirectory;
    });

    workingDirectory = workingDirectory || this.ROOT;
    if (files) {
        this._init(files);
    }
}

MockFs.prototype = Object.create(Boot);

MockFs.prototype._init = function (files, tree) {
    tree = tree || this.ROOT;
    Object.keys(files).forEach(function (path) {
        var content = files[path];
        path = this.join(tree, path);
        var directory = this.directory(path);
        var base = this.base(path);
        var directoryNode = this._root._walk(directory, true);
        var fileNode = new FileNode(this);
        if (!(content instanceof Buffer)) {
            if (typeof content === "object") {
                // make directory
                this._root._walk(path, true);
                // make content
                this._init(content, path);
                return;
            } else {
                content = new Buffer(String(content), "utf-8");
            }
        }
        directoryNode._entries[base] = fileNode;
        fileNode._chunks = [content];
    }, this);
};

MockFs.prototype.list = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        var node = self._root._walk(path)._follow(path);
        if (!node.isDirectory()) {
            new Error("Can't list non-directory: " + JSON.stringify(path));
        }
        return Object.keys(node._entries).sort();
    });
};

MockFs.prototype.open = function (path, flags, charset, options) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        var directory = self.directory(path);
        var base = self.base(path);
        var node = self._root._walk(directory);
        if (!node.isDirectory()) {
            throw new Error("Can't find " + path + " because " + directory + " is not a directory");
        }
        if (typeof flags == "object") {
            options = flags;
            flags = options.flags;
            charset = options.charset;
        } else {
            options = options || {};
        }
        flags = flags || "r";
        var binary = flags.indexOf("b") >= 0;
        var write = flags.indexOf("w") >= 0;
        var append = flags.indexOf("a") >= 0;
        if (!binary) {
            charset = charset || "utf-8";
        }
        if (write || append) {
            if (!node._entries[base]) {
                node._entries[base] = new FileNode(this);
                if ("mode" in options) {
                    node._entries[base].mode = options.mode;
                }
            }
            var fileNode = node._entries[base]._follow(path);
            if (!fileNode.isFile()) {
                throw new Error("Can't write non-file " + path);
            }
            fileNode.mtime = Date.now();
            fileNode.atime = Date.now();
            if (!append) {
                fileNode._chunks.length = 0;
            }
            return new BufferStream(fileNode._chunks, charset);
        } else { // read
            if (!node._entries[base]) {
                throw new Error("Can't read non-existant " + path);
            }
            var fileNode = node._entries[base]._follow(path);
            if (!fileNode.isFile()) {
                throw new Error("Can't read non-file " + path);
            }
            fileNode.atime = Date.now();
            if ("begin" in options && "end" in options) {
                return new BufferStream(
                    [
                        Reader.join(fileNode._chunks)
                        .slice(options.begin, options.end)
                    ],
                    charset
                );
            } else {
                return new BufferStream(fileNode._chunks, charset);
            }
        }
    });
};

MockFs.prototype.remove = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        var directory = self.directory(path);
        var name = self.base(path);
        var node = self._root._walk(directory);
        if (!node.isDirectory()) {
            throw new Error("Can't remove file from non-directory: " + path);
        }
        if (!node._entries[name]) {
            throw new Error("Can't remove non-existant file: " + path);
        }
        if (node._entries[name].isDirectory()) {
            throw new Error("Can't remove directory. Use removeDirectory: " + path);
        }
        delete node._entries[name];
    });
};

MockFs.prototype.makeDirectory = function (path, mode) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        var directory = self.directory(path);
        var name = self.base(path);
        var node = self._root._walk(directory);
        if (!node.isDirectory()) {
            var error =  new Error("Can't make directory in non-directory: " + path);
            error.code = "EEXISTS";
            error.exists = true;
            throw error;
        }
        if (node._entries[name]) {
            var error = new Error("Can't make directory. Entry exists: " + path);
            error.code = "EISDIR";
            error.exists = true;
            error.isDirectory = true;
            throw error;
        }
        node._entries[name] = new DirectoryNode(self);
        if (mode) {
            node._entries[name].mode = mode;
        }
    });
};

MockFs.prototype.removeDirectory = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        var directory = self.directory(path);
        var name = self.base(path);
        var node = self._root._walk(directory);
        if (!node.isDirectory()) {
            throw new Error("Can't remove directory from non-directory: " + path);
        }
        if (!node._entries[name]) {
            throw new Error("Can't remove non-existant directory: " + path);
        }
        if (!node._entries[name].isDirectory()) {
            throw new Error("Can't remove non-directory: " + path);
        }
        delete node._entries[name];
    });
};

MockFs.prototype.stat = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        return new self.Stats(self._root._walk(path)._follow(path));
    });
};

MockFs.prototype.statLink = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        return new self.Stats(self._root._walk(path));
    });
};

MockFs.prototype.link = function (source, target) {
    var self = this;
    return Q.fcall(function () {
        source = self.absolute(source);
        target = self.absolute(target);
        var sourceNode = self._root._walk(source)._follow(source);
        if (!sourceNode.isFile()) {
            throw new Error("Can't link non-file: " + source);
        }
        var directory = self.directory(target);
        var base = self.base(target);
        var targetNode = self._root._walk(directory)._follow(directory);
        if (!targetNode.isDirectory()) {
            throw new Error("Can't create link in non-directory: " + target);
        }
        if (targetNode._entries[base] && targetNode._entries[base].isDirectory()) {
            throw new Error("Can't overwrite existing directory with hard link: " + target);
        }
        targetNode._entries[base] = sourceNode;
    });
};

MockFs.prototype.symbolicLink = function (target, relative, type) {
    var self = this;
    return Q.fcall(function () {
        target = self.absolute(target);
        var directory = self.directory(target);
        var base = self.base(target);
        var node = self._root._walk(directory);
        if (node._entries[base] && node._entries[base].isDirectory()) {
            throw new Error("Can't overwrite existing directory with symbolic link: " + target);
        }
        node._entries[base] = new LinkNode(self, relative);
    });
};

MockFs.prototype.chown = function (path, owner) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        self._root._walk(path)._follow(path)._owner = owner;
    });
};

MockFs.prototype.chmod = function (path, mode) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        self._root._walk(path)._follow(path).mode = mode;
    });
};

MockFs.prototype.rename = function (source, target) {
    var self = this;
    return Q.fcall(function () {
        source = self.absolute(source);
        target = self.absolute(target);

        var sourceDirectory = self.directory(source);
        var sourceDirectoryNode = self._root._walk(sourceDirectory)._follow(sourceDirectory);
        var sourceName = self.base(source);
        var sourceNode = sourceDirectoryNode._entries[sourceName];

        if (!sourceNode) {
            var error = new Error("Can't copy non-existent file: " + source);
            error.code = "ENOENT";
            throw error;
        }

        sourceNode = sourceNode._follow(source);

        // check again after following symbolic links
        if (!sourceNode) {
            var error = new Error("Can't copy non-existent file: " + source);
            error.code = "ENOENT";
            throw error;
        }

        var targetDirectory = self.directory(target);
        var targetDirectoryNode = self._root._walk(targetDirectory)._follow(targetDirectory);
        var targetName = self.base(target);
        var targetNode = targetDirectoryNode._entries[targetName]; // might not exist, not followed

        if (targetNode) {
            targetNode = targetNode._follow(target);
        }

        if (targetNode && targetNode.isDirectory()) {
            var error = new Error("Can't copy over existing directory: " + target);
            error.code = "EISDIR";
            throw error;
        }

        // do not copy over self, even with symbolic links to confuse the issue
        if (targetNode === sourceNode) {
            return;
        }

        targetDirectoryNode._entries[targetName] = sourceNode;
        delete sourceDirectoryNode._entries[sourceName];
    });
};

MockFs.prototype.readLink = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        var node = self._root._walk(path);
        if (!self.isSymbolicLink()) {
            throw new Error("Can't read non-symbolic link: " + path);
        }
        return node._link;
    });
};

MockFs.prototype.canonical = function (path) {
    var self = this;
    return Q.fcall(function () {
        path = self.absolute(path);
        return self._root._canonical(path);
    });
};

MockFs.mock = mock;
function mock(fs, root) {
    return Q.when(fs.listTree(root), function (list) {
        var tree = {};
        return Q.all(list.map(function (path) {
            var actual = fs.join(root, path);
            var relative = fs.relativeFromDirectory(root, actual);
            return Q.when(fs.stat(actual), function (stat) {
                if (stat.isFile()) {
                    return Q.when(fs.read(path, "rb"), function (content) {
                        tree[relative] = content;
                    });
                }
            });
        })).then(function () {
            return MockFs(tree);
        });
    });
}

function Node(fs) {
    if (!fs)
        throw new Error("FS required argument");
    this._fs = fs;
    this.atime = this.mtime = Date.now();
    this.mode = parseInt("0644", 8);
    this._owner = null;
}

Node.prototype._walk = function (path, make, via) {
    var parts = this._fs.split(path);
    if (this._fs.isAbsolute(path)) {
        parts.shift();
        return this._fs._root._walkParts(parts, make, this._fs.ROOT);
    } else {
        return this._walkParts(parts, make, via || this._fs.ROOT);
    }
};

Node.prototype._walkParts = function (parts, make, via) {
    if (parts.length === 0) {
        return this;
    } else {
        var part = parts.shift();
        if (part === "") {
            return this._walkParts(parts, make, this._fs.join(via, part));
        } else {
            var error = new Error("Can't find " + JSON.stringify(this._fs.resolve(part, this._fs.join(parts))) + " via " + JSON.stringify(via));
            error.code = "ENOENT";
            throw error;
        }
    }
};

Node.prototype._canonical = function (path) {
    if (!this._fs.isAbsolute(path)) {
        throw new Error("Path must be absolute for _canonical: " + path);
    }
    var parts = this._fs.split(path);
    parts.shift();
    var via = this._fs.ROOT;
    return via + this._fs._root._canonicalParts(parts, via);
};

Node.prototype._canonicalParts = function (parts, via) {
    if (parts.length === 0) {
        return via;
    }
    return this._fs.join(via, this._fs.join(parts));
};

Node.prototype._follow = function () {
    return this;
};

Node.prototype._touch = function () {
    this.mtime = Date.now();
};

var stats = [
    "isDirectory",
    "isFile",
    "isBlockDevice",
    "isCharacterDevice",
    "isSymbolicLink",
    "isFIFO",
    "isSocket"
];

stats.forEach(function (name) {
    Node.prototype[name] = function () {
        return false;
    };
});

Node.prototype.lastAccessed = function () {
    return this.atime;
};

Node.prototype.lastModified = function () {
    return this.mtime;
};

function FileNode(fs) {
    Node.call(this, fs);
    this._chunks = [];
}

FileNode.prototype = Object.create(Node.prototype);

FileNode.prototype.isFile = function () {
    return true;
};

Object.defineProperty(FileNode.prototype, "size", {
    configurable: true,
    enumerable: true,
    get: function () {
        return this._chunks.reduce(function (size, chunk) {
            return size += chunk.length;
        }, 0);
    }
});

function DirectoryNode(fs) {
    Node.call(this, fs);
    this._entries = Object.create(null);
    this.mode = parseInt("0755", 8);
}

DirectoryNode.prototype = Object.create(Node.prototype);

DirectoryNode.prototype.isDirectory = function () {
    return true;
};

DirectoryNode.prototype._walkParts = function (parts, make, via) {
    via = via || this._fs.ROOT;
    if (parts.length === 0) {
        return this;
    }
    var part = parts.shift();
    if (part === "") {
        return this._walkParts(parts, make, this._fs.join(via, part));
    }
    if (!this._entries[part]) {
        if (make) {
            this._entries[part] = new DirectoryNode(this._fs);
        } else {
            var error = new Error("Can't find " + JSON.stringify(this._fs.join(parts)) + " via " + JSON.stringify(via));
            error.code = "ENOENT";
            throw error;

        }
    }
    return this._entries[part]._walkParts(parts, make, this._fs.join(via, part));
};

DirectoryNode.prototype._canonicalParts = function (parts, via) {
    if (parts.length === 0) {
        return via;
    }
    var part = parts.shift();
    if (part === "") {
        return via;
    }
    if (via === this._fs.ROOT) {
        via = "";
    }
    if (!this._entries[part]) {
        return this._fs.join(via, part, this._fs.join(parts));
    }
    return this._entries[part]._canonicalParts(
        parts,
        this._fs.join(via, part)
    );
};

function LinkNode(fs, link) {
    Node.call(this, fs);
    this._link = link;
}

LinkNode.prototype = Object.create(Node.prototype);

LinkNode.prototype.isSymbolicLink = function () {
    return true;
};

LinkNode.prototype._follow = function (via, memo) {
    memo = memo || Set();
    if (memo.has(this)) {
        var error = new Error("Can't follow symbolic link cycle at " + JSON.stringify(via));
        error.code = "ELOOP";
        throw error;
    }
    memo.add(this);
    var link = this._fs.join(via, "..", this._link);
    return this._walk(link, null, "<link>")._follow(link, memo);
};

LinkNode.prototype._canonicalParts = function (parts, via) {
    return this._fs.relativeFromDirectory(this._fs.ROOT,
        this._fs._root._canonical(
            this._fs.absolute(this._fs.join(via, "..", this._link))
        )
    );
};

// cycle breaking
var FS = require("./fs");