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.

390 lines (354 loc) 12.6 kB
Object.defineProperty(exports, '__esModule', { value: true }); /* * 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. */ var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } var _commonsNodeNuclideUri2; function _commonsNodeNuclideUri() { return _commonsNodeNuclideUri2 = _interopRequireDefault(require('../../commons-node/nuclideUri')); } var _crypto2; function _crypto() { return _crypto2 = _interopRequireDefault(require('crypto')); } var _atom2; function _atom() { return _atom2 = require('atom'); } var _nuclideLogging2; function _nuclideLogging() { return _nuclideLogging2 = require('../../nuclide-logging'); } var logger = (0, (_nuclideLogging2 || _nuclideLogging()).getLogger)(); /* Mostly implements https://atom.io/docs/api/latest/File */ var RemoteFile = (function () { function RemoteFile(server, remotePath) { var symlink = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; _classCallCheck(this, RemoteFile); this._server = server; this.setPath(remotePath); this._emitter = new (_atom2 || _atom()).Emitter(); this._subscriptionCount = 0; this._deleted = false; this._symlink = symlink; } _createClass(RemoteFile, [{ key: 'dispose', value: function dispose() { this._subscriptionCount = 0; this._unsubscribeFromNativeChangeEvents(); } }, { key: 'onDidChange', value: function onDidChange(callback) { this._willAddSubscription(); return this._trackUnsubscription(this._emitter.on('did-change', callback)); } }, { key: 'onDidRename', value: function onDidRename(callback) { this._willAddSubscription(); return this._trackUnsubscription(this._emitter.on('did-rename', callback)); } }, { key: 'onDidDelete', value: function onDidDelete(callback) { this._willAddSubscription(); return this._trackUnsubscription(this._emitter.on('did-delete', callback)); } }, { key: '_willAddSubscription', value: function _willAddSubscription() { this._subscriptionCount++; return this._subscribeToNativeChangeEvents(); } }, { key: '_subscribeToNativeChangeEvents', value: function _subscribeToNativeChangeEvents() { var _this = this; if (this._watchSubscription) { return; } var _ref = this._getService('FileWatcherService'); var watchFile = _ref.watchFile; var watchStream = watchFile(this._path).refCount(); this._watchSubscription = watchStream.subscribe(function (watchUpdate) { logger.debug('watchFile update:', watchUpdate); switch (watchUpdate.type) { case 'change': return _this._handleNativeChangeEvent(); case 'delete': return _this._handleNativeDeleteEvent(); case 'rename': return _this._handleNativeRenameEvent(watchUpdate.path); } }, function (error) { logger.error('Failed to subscribe RemoteFile:', _this._path, error); _this._watchSubscription = null; }, function () { // Nothing needs to be done if the root directory watch has ended. logger.debug('watchFile ended: ' + _this._path); _this._watchSubscription = null; }); } }, { key: '_handleNativeChangeEvent', value: _asyncToGenerator(function* () { // Don't bother checking the file - this can be very expensive. this._emitter.emit('did-change'); }) }, { key: '_handleNativeRenameEvent', value: function _handleNativeRenameEvent(newPath) { this._unsubscribeFromNativeChangeEvents(); var _default$parse = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parse(this._path); var protocol = _default$parse.protocol; var host = _default$parse.host; this._localPath = newPath; (0, (_assert2 || _assert()).default)(protocol); (0, (_assert2 || _assert()).default)(host); this._path = protocol + '//' + host + this._localPath; this._subscribeToNativeChangeEvents(); this._emitter.emit('did-rename'); } }, { key: '_handleNativeDeleteEvent', value: function _handleNativeDeleteEvent() { this._unsubscribeFromNativeChangeEvents(); if (!this._deleted) { this._deleted = true; this._emitter.emit('did-delete'); } } /* * Return a new Disposable that upon dispose, will remove the bound watch subscription. * When the number of subscriptions reach 0, the file is unwatched. */ }, { key: '_trackUnsubscription', value: function _trackUnsubscription(subscription) { var _this2 = this; return new (_atom2 || _atom()).Disposable(function () { subscription.dispose(); _this2._didRemoveSubscription(); }); } }, { key: '_didRemoveSubscription', value: function _didRemoveSubscription() { this._subscriptionCount--; if (this._subscriptionCount === 0) { this._unsubscribeFromNativeChangeEvents(); } } }, { key: '_unsubscribeFromNativeChangeEvents', value: function _unsubscribeFromNativeChangeEvents() { if (this._watchSubscription) { this._watchSubscription.unsubscribe(); this._watchSubscription = null; } } }, { key: 'onWillThrowWatchError', value: function onWillThrowWatchError(callback) { return this._emitter.on('will-throw-watch-error', callback); } }, { key: 'isFile', value: function isFile() { return true; } }, { key: 'isDirectory', value: function isDirectory() { return false; } }, { key: 'exists', value: function exists() { return this._getFileSystemService().exists(this._localPath); } }, { key: 'existsSync', value: function existsSync() { return true; } }, { key: 'getDigestSync', value: function getDigestSync() { if (!this._digest) { // File's `getDigestSync()` calls `readSync()`, which we don't implement. // However, we mimic it's behavior for when a file does not exist. this._setDigest(''); } (0, (_assert2 || _assert()).default)(this._digest); return this._digest; } }, { key: 'getDigest', value: _asyncToGenerator(function* () { if (this._digest) { return this._digest; } yield this.read(); (0, (_assert2 || _assert()).default)(this._digest); return this._digest; }) }, { key: '_setDigest', value: function _setDigest(contents) { var hash = (_crypto2 || _crypto()).default.createHash('sha1').update(contents || ''); (0, (_assert2 || _assert()).default)(hash); this._digest = hash.digest('hex'); } }, { key: 'setEncoding', value: function setEncoding(encoding) { this._encoding = encoding; } }, { key: 'getEncoding', value: function getEncoding() { return this._encoding; } }, { key: 'setPath', value: function setPath(remotePath) { var _default$parse2 = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parse(remotePath); var localPath = _default$parse2.path; this._localPath = localPath; this._path = remotePath; } }, { key: 'getPath', value: function getPath() { return this._path; } }, { key: 'getLocalPath', value: function getLocalPath() { return this._localPath; } }, { key: 'getRealPathSync', value: function getRealPathSync() { return this._realpath || this._path; } }, { key: 'getRealPath', value: _asyncToGenerator(function* () { if (this._realpath == null) { this._realpath = yield this._getFileSystemService().realpath(this._localPath); } (0, (_assert2 || _assert()).default)(this._realpath); return this._realpath; }) }, { key: 'getBaseName', value: function getBaseName() { return (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.basename(this._path); } }, { key: 'create', value: _asyncToGenerator(function* () { var wasCreated = yield this._getFileSystemService().newFile(this._localPath); if (this._subscriptionCount > 0) { this._subscribeToNativeChangeEvents(); } return wasCreated; }) }, { key: 'delete', value: _asyncToGenerator(function* () { try { yield this._getFileSystemService().unlink(this._localPath); this._handleNativeDeleteEvent(); } catch (error) { if (error.code !== 'ENOENT') { throw error; } } }) }, { key: 'rename', value: _asyncToGenerator(function* (newPath) { yield this._getFileSystemService().rename(this._localPath, newPath); this._handleNativeRenameEvent(newPath); }) }, { key: 'copy', value: _asyncToGenerator(function* (newPath) { var wasCopied = yield this._getFileSystemService().copy(this._localPath, newPath); this._subscribeToNativeChangeEvents(); return wasCopied; }) }, { key: 'read', value: _asyncToGenerator(function* (flushCache) { var data = yield this._getFileSystemService().readFile(this._localPath); var contents = data.toString(); this._setDigest(contents); // TODO: respect encoding return contents; }) }, { key: 'readSync', value: function readSync(flushcache) { throw new Error('readSync is not supported in RemoteFile'); } }, { key: 'write', value: _asyncToGenerator(function* (text) { var previouslyExisted = yield this.exists(); yield this._getFileSystemService().writeFile(this._localPath, text); if (!previouslyExisted && this._subscriptionCount > 0) { this._subscribeToNativeChangeEvents(); } }) }, { key: 'getParent', value: function getParent() { var _default$parse3 = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parse(this._path); var localPath = _default$parse3.path; var protocol = _default$parse3.protocol; var host = _default$parse3.host; (0, (_assert2 || _assert()).default)(protocol); (0, (_assert2 || _assert()).default)(host); var directoryPath = protocol + '//' + host + (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.dirname(localPath); var remoteConnection = this._server.getRemoteConnectionForUri(this._path); var hgRepositoryDescription = remoteConnection != null ? remoteConnection.getHgRepositoryDescription() : null; return this._server.createDirectory(directoryPath, hgRepositoryDescription); } }, { key: 'isSymbolicLink', value: function isSymbolicLink() { return this._symlink; } }, { key: '_getFileSystemService', value: function _getFileSystemService() { return this._getService('FileSystemService'); } }, { key: '_getService', value: function _getService(serviceName) { return this._server.getService(serviceName); } }]); return RemoteFile; })(); exports.RemoteFile = RemoteFile;