Model for a File.
This class should not be instantiated directly. Use FileSystem.getFileForPath, FileSystem.resolve, or Directory.getContents to create an instance of this class.
See the FileSystem class for more details.
function File(fullPath, fileSystem) {
this._isFile = true;
FileSystemEntry.call(this, fullPath, fileSystem);
}
File.prototype = Object.create(FileSystemEntry.prototype);
File.prototype.constructor = File;
File.prototype.parentClass = FileSystemEntry.prototype;
Cached contents of this file. This value is nullable but should NOT be undefined.
File.prototype._contents = null;
Consistency hash for this file. Reads and writes update this value, and writes confirm the hash before overwriting existing files. The type of this object is dependent on the FileSystemImpl; the only constraint is that === can be used as an equality relation on hashes.
File.prototype._hash = null;
Clear any cached data for this file. Note that this explicitly does NOT clear the file's hash.
File.prototype._clearCachedData = function () {
FileSystemEntry.prototype._clearCachedData.apply(this);
this._contents = null;
};
Read a file.
File.prototype.read = function (options, callback) {
if (typeof (options) === "function") {
callback = options;
options = {};
options.encoding = this._encoding;
}
options.encoding = this._encoding || "utf8";
// We don't need to check isWatched() here because contents are only saved
// for watched files. Note that we need to explicitly test this._contents
// for a default value; otherwise it could be the empty string, which is
// falsey.
if (this._contents !== null && this._stat) {
callback(null, this._contents, this._encoding, this._stat);
return;
}
var watched = this._isWatched();
if (watched) {
options.stat = this._stat;
}
this._impl.readFile(this._path, options, function (err, data, encoding, preserveBOM, stat) {
if (err) {
this._clearCachedData();
callback(err);
return;
}
// Always store the hash
this._hash = stat._hash;
this._encoding = encoding;
this._preserveBOM = preserveBOM;
// Only cache data for watched files
if (watched) {
this._stat = stat;
this._contents = data;
}
callback(err, data, encoding, stat);
}.bind(this));
};
Write a file.
File.prototype.write = function (data, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
} else {
if (options === undefined) {
options = {};
}
callback = callback || function () {};
}
// Request a consistency check if the write is not blind
if (!options.blind) {
options.expectedHash = this._hash;
options.expectedContents = this._contents;
}
if (!options.encoding) {
options.encoding = this._encoding || "utf8";
}
options.preserveBOM = this._preserveBOM;
// Block external change events until after the write has finished
this._fileSystem._beginChange();
this._impl.writeFile(this._path, data, options, function (err, stat, created) {
if (err) {
this._clearCachedData();
try {
callback(err);
return;
} finally {
// Always unblock external change events
this._fileSystem._endChange();
}
}
// Always store the hash
this._hash = stat._hash;
// Only cache data for watched files
if (this._isWatched()) {
this._stat = stat;
this._contents = data;
}
if (created) {
var parent = this._fileSystem.getDirectoryForPath(this.parentPath);
this._fileSystem._handleDirectoryChange(parent, function (added, removed) {
try {
// Notify the caller
callback(null, stat);
} finally {
if (parent._isWatched()) {
// If the write succeeded and the parent directory is watched,
// fire a synthetic change event
this._fileSystem._fireChangeEvent(parent, added, removed);
}
// Always unblock external change events
this._fileSystem._endChange();
}
}.bind(this));
} else {
try {
// Notify the caller
callback(null, stat);
} finally {
// existing file modified
this._fileSystem._fireChangeEvent(this);
// Always unblock external change events
this._fileSystem._endChange();
}
}
}.bind(this));
};
// Export this class
module.exports = File;
});