Modules (188)

Directory

Description

Dependencies

Functions

Private

_applyAllCallbacks

Apply each callback in a list to the provided arguments. Callbacks can throw without preventing other callbacks from being applied.

callbacks Array.<function>
The callbacks to apply
args Array
The arguments to which each callback is applied
    function _applyAllCallbacks(callbacks, args) {
        if (callbacks.length > 0) {
            var callback = callbacks.pop();
            try {
                callback.apply(undefined, args);
            } finally {
                _applyAllCallbacks(callbacks, args);
            }
        }
    }

Classes

Constructor

Directory

Model for a file system Directory.

This class should not be instantiated directly. Use FileSystem.getDirectoryForPath, FileSystem.resolve, or Directory.getContents to create an instance of this class.

Note: Directory.fullPath always has a trailing slash.

See the FileSystem class for more details.

fullPath string
The full path for this Directory.
fileSystem FileSystem
The file system associated with this Directory.
    function Directory(fullPath, fileSystem) {
        this._isDirectory = true;
        FileSystemEntry.call(this, fullPath, fileSystem);
    }

    Directory.prototype = Object.create(FileSystemEntry.prototype);
    Directory.prototype.constructor = Directory;
    Directory.prototype.parentClass = FileSystemEntry.prototype;

Properties

Private

_contents

The contents of this directory. This "private" property is used by FileSystem.

Type
Array<FileSystemEntry>
    Directory.prototype._contents = null;
Private

_contentsStats

The stats for the contents of this directory, such that this._contentsStats[i] corresponds to this._contents[i].

Type
Array.<FileSystemStats>
    Directory.prototype._contentsStats = null;
Private

_contentsStatsErrors

The stats errors for the contents of this directory.

Type
object.<string: string>
    Directory.prototype._contentsStatsErrors = null;

Methods

Private

_clearCachedData

Clear any cached data for this directory. By default, we clear the contents of immediate children as well, because in some cases file watchers fail provide precise change notifications. (Sometimes, like after a "git checkout", they just report that some directory has changed when in fact many of the file within the directory have changed.

preserveImmediateChildren optional boolean
    Directory.prototype._clearCachedData = function (preserveImmediateChildren) {
        FileSystemEntry.prototype._clearCachedData.apply(this);

        if (!preserveImmediateChildren) {
            if (this._contents) {
                this._contents.forEach(function (child) {
                    child._clearCachedData(true);
                });
            } else {
                // No cached _contents, but child entries may still exist.
                // Scan the full index to catch all of them.
                var dirPath = this.fullPath;
                this._fileSystem._index.visitAll(function (entry) {
                    if (entry.parentPath === dirPath) {
                        entry._clearCachedData(true);
                    }
                });
            }
        }

        this._contents = undefined;
        this._contentsStats = undefined;
        this._contentsStatsErrors = undefined;
    };

create

Create a directory

callback optional function (?string, FileSystemStats=)
Callback resolved with a FileSystemError string or the stat object for the created directory.
    Directory.prototype.create = function (callback) {
        callback = callback || function () {};

        // Block external change events until after the write has finished
        this._fileSystem._beginChange();

        this._impl.mkdir(this._path, function (err, stat) {
            if (err) {
                this._clearCachedData();
                try {
                    callback(err);
                    return;
                } finally {
                    // Unblock external change events
                    this._fileSystem._endChange();
                }
            }

            var parent = this._fileSystem.getDirectoryForPath(this.parentPath);

            // Update internal filesystem state
            if (this._isWatched()) {
                this._stat = stat;
            }

            this._fileSystem._handleDirectoryChange(parent, function (added, removed) {
                try {
                    callback(null, stat);
                } finally {
                    if (parent._isWatched()) {
                        this._fileSystem._fireChangeEvent(parent, added, removed);
                    }
                    // Unblock external change events
                    this._fileSystem._endChange();
                }
            }.bind(this));
        }.bind(this));
    };

    // Export this class
    module.exports = Directory;
});

getContents

Read the contents of a Directory. If this Directory is under a watch root, the listing will exclude any items filtered out by the watch root's filter function.

directory Directory
Directory whose contents you want to get
callback function (?string,Array.<FileSystemEntry>=,Array.<FileSystemStats>=,Object.<string,string>=)
Callback that is passed an error code or the stat-able contents of the directory along with the stats for these entries and a fullPath-to-FileSystemError string map of unstat-able entries and their stat errors. If there are no stat errors then the last parameter shall remain undefined.
    Directory.prototype.getContents = function (callback) {
        if (this._contentsCallbacks) {
            // There is already a pending call for this directory's contents.
            // Push the new callback onto the stack and return.
            this._contentsCallbacks.push(callback);
            return;
        }

        // Return cached contents if the directory is watched
        if (this._contents) {
            callback(null, this._contents, this._contentsStats, this._contentsStatsErrors);
            return;
        }

        this._contentsCallbacks = [callback];

        this._impl.readdir(this.fullPath, function (err, names, stats) {
            var contents = [],
                contentsStats = [],
                contentsStatsErrors;

            if (err) {
                this._clearCachedData();
            } else {
                // Use the "relaxed" parameter to _isWatched because it's OK to
                // cache data even while watchers are still starting up
                var watched = this._isWatched(true);

                names.forEach(function (name, index) {
                    var entryPath = this.fullPath + name;

                    var entryStats = stats[index];
                    if (this._fileSystem._indexFilter(entryPath, name, entryStats)) {
                        var entry;

                        // Note: not all entries necessarily have associated stats.
                        if (typeof entryStats === "string") {
                            // entryStats is an error string
                            if (contentsStatsErrors === undefined) {
                                contentsStatsErrors = {};
                            }
                            contentsStatsErrors[entryPath] = entryStats;
                        } else {
                            // entryStats is a FileSystemStats object
                            if (entryStats.isFile) {
                                entry = this._fileSystem.getFileForPath(entryPath);
                            } else {
                                entry = this._fileSystem.getDirectoryForPath(entryPath);
                            }

                            if (watched) {
                                entry._stat = entryStats;
                            }

                            contents.push(entry);
                            contentsStats.push(entryStats);
                        }
                    }
                }, this);

                if (watched) {
                    this._contents = contents;
                    this._contentsStats = contentsStats;
                    this._contentsStatsErrors = contentsStatsErrors;
                }
            }

            // Reset the callback list before we begin calling back so that
            // synchronous reentrant calls are handled correctly.
            var currentCallbacks = this._contentsCallbacks;

            this._contentsCallbacks = null;

            // Invoke all saved callbacks
            var callbackArgs = [err, contents, contentsStats, contentsStatsErrors];
            _applyAllCallbacks(currentCallbacks, callbackArgs);
        }.bind(this));
    };