UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

396 lines (330 loc) 12.6 kB
Object.defineProperty(exports, '__esModule', { value: true }); exports.exists = exists; exports.findNearestFile = findNearestFile; exports.lstat = lstat; exports.mkdir = mkdir; exports.mkdirp = mkdirp; exports.chmod = chmod; /** * If no file (or directory) at the specified path exists, creates the parent * directories (if necessary) and then writes an empty file at the specified * path. * * @return A boolean indicating whether the file was created. */ var newFile = _asyncToGenerator(function* (filePath) { var isExistingFile = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.exists(filePath); if (isExistingFile) { return false; } yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.mkdirp((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.dirname(filePath)); yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.writeFile(filePath, ''); return true; } /** * The readdir endpoint accepts the following query parameters: * * path: path to the folder to list entries inside. * * Body contains a JSON encoded array of objects with file: and stats: entries. * file: has the file or directory name, stats: has the stats of the file/dir, * isSymbolicLink: true if the entry is a symlink to another filesystem location. */ ); exports.newFile = newFile; var readdir = _asyncToGenerator(function* (path) { var files = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.readdir(path); var entries = yield Promise.all(files.map(_asyncToGenerator(function* (file) { var fullpath = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.join(path, file); var lstats = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.lstat(fullpath); if (!lstats.isSymbolicLink()) { return { file: file, stats: lstats, isSymbolicLink: false }; } else { try { var _stats = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.stat(fullpath); return { file: file, stats: _stats, isSymbolicLink: true }; } catch (error) { return { file: file, stats: undefined, isSymbolicLink: true, error: error }; } } }))); // TODO: Return entries directly and change client to handle error. return entries.filter(function (entry) { return entry.error === undefined; }).map(function (entry) { return { file: entry.file, stats: entry.stats, isSymbolicLink: entry.isSymbolicLink }; }); } /** * Gets the real path of a file path. * It could be different than the given path if the file is a symlink * or exists in a symlinked directory. */ ); exports.readdir = readdir; exports.realpath = realpath; exports.resolveRealPath = resolveRealPath; exports.rename = rename; /** * Moves all sourcePaths into the specified destDir, assumed to be a directory name. */ var move = _asyncToGenerator(function* (sourcePaths, destDir) { yield Promise.all(sourcePaths.map(function (path) { var destPath = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.join(destDir, (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.basename(path)); return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.move(path, destPath); })); } /** * Runs the equivalent of `cp sourcePath destinationPath`. * @return true if the operation was successful; false if it wasn't. */ ); exports.move = move; var copy = _asyncToGenerator(function* (sourcePath, destinationPath) { var isExistingFile = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.exists(destinationPath); if (isExistingFile) { return false; } yield new Promise(function (resolve, reject) { (_fsPlus2 || _fsPlus()).default.copy(sourcePath, destinationPath, function (error) { error ? reject(error) : resolve(); }); }); yield copyFilePermissions(sourcePath, destinationPath); return true; } /** * Removes directories even if they are non-empty. Does not fail if the directory doesn't exist. */ ); exports.copy = copy; exports.rmdir = rmdir; var rmdirAll = _asyncToGenerator(function* (paths) { yield Promise.all(paths.map(function (p) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.rmdir(p); })); } /** * The stat endpoint accepts the following query parameters: * * path: path to the file to read * * It returns a JSON encoded stats object that looks something like this: * * { dev: 2114, * ino: 48064969, * mode: 33188, * nlink: 1, * uid: 85, * gid: 100, * rdev: 0, * size: 527, * blksize: 4096, * blocks: 8, * atime: 'Mon, 10 Oct 2011 23:24:11 GMT', * mtime: 'Mon, 10 Oct 2011 23:24:11 GMT', * ctime: 'Mon, 10 Oct 2011 23:24:11 GMT', * birthtime: 'Mon, 10 Oct 2011 23:24:11 GMT' * } * */ ); exports.rmdirAll = rmdirAll; exports.stat = stat; exports.unlink = unlink; /** * path: the path to the file to read * options: options to pass to fs.readFile. * Note that options does NOT include 'encoding' this ensures that the return value * is always a Buffer and never a string. * * Callers who want a string should call buffer.toString('utf8'). */ var readFile = _asyncToGenerator(function* (path, options) { var stats = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.stat(path); if (stats.size > READFILE_SIZE_LIMIT) { throw new Error('File is too large (' + stats.size + ' bytes)'); } return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.readFile(path, options); } /** * Returns true if the path being checked exists in a `NFS` mounted directory device. */ ); exports.readFile = readFile; exports.isNfs = isNfs; var copyFilePermissions = _asyncToGenerator(function* (sourcePath, destinationPath) { var permissions = null; try { permissions = (yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.stat(sourcePath)).mode; } catch (e) { // If the file does not exist, then ENOENT will be thrown. if (e.code !== 'ENOENT') { throw e; } } if (permissions != null) { yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.chmod(destinationPath, permissions); } } /** * The writeFile endpoint accepts the following query parameters: * * path: path to the file to read (it must be url encoded). * data: file contents to write. * options: options to pass to fs.writeFile * * TODO: move to nuclide-commons and rename to writeFileAtomic */ ); var writeFile = _asyncToGenerator(function* (path, data, options) { var complete = false; var tempFilePath = yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.tempfile('nuclide'); try { yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.writeFile(tempFilePath, data, options); // Ensure file still has original permissions: // https://github.com/facebook/nuclide/issues/157 // We update the mode of the temp file rather than the destination file because // if we did the mv() then the chmod(), there would be a brief period between // those two operations where the destination file might have the wrong permissions. yield copyFilePermissions(path, tempFilePath); // TODO(mikeo): put renames into a queue so we don't write older save over new save. // Use mv as fs.rename doesn't work across partitions. yield mvPromise(tempFilePath, path); complete = true; } finally { if (!complete) { yield (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.unlink(tempFilePath); } } }); exports.writeFile = writeFile; function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { var callNext = step.bind(null, 'next'); var callThrow = step.bind(null, 'throw'); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(callNext, callThrow); } } callNext(); }); }; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ /** * This code implements the NuclideFs service. It exports the FS on http via * the endpoint: http://your.server:your_port/fs/method where method is one of * readFile, writeFile, etc. */ var _mv2; function _mv() { return _mv2 = _interopRequireDefault(require('mv')); } var _fs2; function _fs() { return _fs2 = _interopRequireDefault(require('fs')); } var _fsPlus2; function _fsPlus() { return _fsPlus2 = _interopRequireDefault(require('fs-plus')); } var _commonsNodeNuclideUri2; function _commonsNodeNuclideUri() { return _commonsNodeNuclideUri2 = _interopRequireDefault(require('../../../commons-node/nuclideUri')); } var _commonsNodeFsPromise2; function _commonsNodeFsPromise() { return _commonsNodeFsPromise2 = _interopRequireDefault(require('../../../commons-node/fsPromise')); } // Attempting to read large files just crashes node, so just fail. // Atom can't handle files of this scale anyway. var READFILE_SIZE_LIMIT = 10 * 1024 * 1024; //------------------------------------------------------------------------------ // Services //------------------------------------------------------------------------------ /** * Checks a certain path for existence and returns 'true'/'false' accordingly */ function exists(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.exists(path); } function findNearestFile(fileName, pathToDirectory) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.findNearestFile(fileName, pathToDirectory); } /** * The lstat endpoint is the same as the stat endpoint except it will return * the stat of a link instead of the file the link points to. */ function lstat(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.lstat(path); } /** * Creates a new directory with the given path. * Throws EEXIST error if the directory already exists. * Throws ENOENT if the path given is nested in a non-existing directory. */ function mkdir(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.mkdir(path); } /** * Runs the equivalent of `mkdir -p` with the given path. * * Like most implementations of mkdirp, if it fails, it is possible that * directories were created for some prefix of the given path. * @return true if the path was created; false if it already existed. */ function mkdirp(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.mkdirp(path); } /** * Changes permissions on a file. */ function chmod(path, mode) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.chmod(path, mode); } function realpath(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.realpath(path); } /** * Gets the real path of a file path, while expanding tilda paths and symlinks * like: ~/abc to its absolute path format. */ function resolveRealPath(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.realpath((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.expandHomeDir(path)); } /** * Runs the equivalent of `mv sourcePath destinationPath`. */ function rename(sourcePath, destinationPath) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.move(sourcePath, destinationPath); } function rmdir(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.rmdir(path); } function stat(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.stat(path); } /** * Removes files. Does not fail if the file doesn't exist. */ function unlink(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.unlink(path).catch(function (error) { if (error.code !== 'ENOENT') { throw error; } }); } function isNfs(path) { return (_commonsNodeFsPromise2 || _commonsNodeFsPromise()).default.isNfs(path); } // TODO: Move to nuclide-commons function mvPromise(sourcePath, destinationPath) { return new Promise(function (resolve, reject) { (0, (_mv2 || _mv()).default)(sourcePath, destinationPath, { mkdirp: false }, function (error) { if (error) { reject(error); } else { resolve(); } }); }); }