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.

416 lines (372 loc) 14.5 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 _atom2; function _atom() { return _atom2 = require('atom'); } var _nuclideLogging2; function _nuclideLogging() { return _nuclideLogging2 = require('../../nuclide-logging'); } var logger = (0, (_nuclideLogging2 || _nuclideLogging()).getLogger)(); var MARKER_PROPERTY_FOR_REMOTE_DIRECTORY = '__nuclide_remote_directory__'; /* Mostly implements https://atom.io/docs/api/latest/Directory */ var RemoteDirectory = (function () { _createClass(RemoteDirectory, null, [{ key: 'isRemoteDirectory', value: function isRemoteDirectory(directory) { /* $FlowFixMe */ return directory[MARKER_PROPERTY_FOR_REMOTE_DIRECTORY] === true; } }]); /** * @param uri should be of the form "nuclide://example.com/path/to/directory". */ function RemoteDirectory(server, uri, symlink, options) { if (symlink === undefined) symlink = false; _classCallCheck(this, RemoteDirectory); Object.defineProperty(this, MARKER_PROPERTY_FOR_REMOTE_DIRECTORY, { value: true }); this._server = server; this._uri = uri; this._emitter = new (_atom2 || _atom()).Emitter(); this._subscriptionCount = 0; this._symlink = symlink; var _default$parse = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parse(uri); var directoryPath = _default$parse.path; var protocol = _default$parse.protocol; var host = _default$parse.host; (0, (_assert2 || _assert()).default)(protocol); (0, (_assert2 || _assert()).default)(host); /** In the example, this would be "nuclide://example.com". */ this._host = host; /** In the example, this would be "/path/to/directory". */ this._localPath = directoryPath; // A workaround before Atom 2.0: see ::getHgRepoInfo of main.js. this._hgRepositoryDescription = options ? options.hgRepositoryDescription : null; this._deleted = false; } _createClass(RemoteDirectory, [{ 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: 'onDidDelete', value: function onDidDelete(callback) { this._willAddSubscription(); return this._trackUnsubscription(this._emitter.on('did-delete', callback)); } }, { key: '_willAddSubscription', value: function _willAddSubscription() { this._subscriptionCount++; try { this._subscribeToNativeChangeEvents(); } catch (err) { logger.error('Failed to subscribe RemoteDirectory:', this._localPath, err); } } }, { key: '_subscribeToNativeChangeEvents', value: function _subscribeToNativeChangeEvents() { var _this = this; if (this._watchSubscription) { return; } var _ref = this._getService('FileWatcherService'); var watchDirectory = _ref.watchDirectory; var watchStream = watchDirectory(this._uri).refCount(); this._watchSubscription = watchStream.subscribe(function (watchUpdate) { logger.debug('watchDirectory update:', watchUpdate); switch (watchUpdate.type) { case 'change': return _this._handleNativeChangeEvent(); case 'delete': return _this._handleNativeDeleteEvent(); } }, function (error) { // TODO: Atom's Git repository API is still synchronous, so it creates RemoteDirectories for // non-existent potential .git directories and checks their existence. This causes log spam, // which is especially painful for testing. if ((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.basename(_this._uri) !== '.git') { logger.error('Failed to subscribe RemoteDirectory:', _this._uri, error); } _this._watchSubscription = null; }, function () { // Nothing needs to be done if the root directory watch has ended. logger.debug('watchDirectory ended: ' + _this._uri); _this._watchSubscription = null; }); } }, { key: '_handleNativeChangeEvent', value: function _handleNativeChangeEvent() { this._emitter.emit('did-change'); } }, { key: '_handleNativeDeleteEvent', value: function _handleNativeDeleteEvent() { this._unsubscribeFromNativeChangeEvents(); if (!this._deleted) { this._deleted = true; this._emitter.emit('did-delete'); } } }, { 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) { return this._unsubscribeFromNativeChangeEvents(); } } }, { key: '_unsubscribeFromNativeChangeEvents', value: function _unsubscribeFromNativeChangeEvents() { if (this._watchSubscription) { try { this._watchSubscription.unsubscribe(); } catch (error) { logger.warn('RemoteDirectory failed to unsubscribe from native events:', this._uri, error.message); } this._watchSubscription = null; } } }, { key: 'isFile', value: function isFile() { return false; } }, { key: 'isDirectory', value: function isDirectory() { return true; } }, { key: 'isRoot', value: function isRoot() { return this._isRoot(this._localPath); } }, { key: 'exists', value: function exists() { return this._getFileSystemService().exists(this._localPath); } }, { key: 'existsSync', value: function existsSync() { return false; } }, { key: '_isRoot', value: function _isRoot(filePath_) { var filePath = filePath_; filePath = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.normalize(filePath); var parts = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parsePath(filePath); return parts.root === filePath; } }, { key: 'getPath', value: function getPath() { return this._uri; } }, { key: 'getLocalPath', value: function getLocalPath() { return this._localPath; } }, { key: 'getRealPathSync', value: function getRealPathSync() { throw new Error('Not implemented'); } }, { key: 'getBaseName', value: function getBaseName() { return (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.basename(this._localPath); } }, { key: 'relativize', value: function relativize(uri) { if (!uri) { return uri; } // Note: host of uri must match this._host. var subpath = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parse(uri).path; return (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.relative(this._localPath, subpath); } }, { key: 'getParent', value: function getParent() { if (this.isRoot()) { return this; } else { var uri = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.createRemoteUri(this._host, (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.dirname(this._localPath)); return this._server.createDirectory(uri, this._hgRepositoryDescription); } } }, { key: 'getFile', value: function getFile(filename) { var uri = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.createRemoteUri(this._host, (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.join(this._localPath, filename)); return this._server.createFile(uri); } }, { key: 'getSubdirectory', value: function getSubdirectory(dir) { var uri = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.createRemoteUri(this._host, (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.join(this._localPath, dir)); return this._server.createDirectory(uri, this._hgRepositoryDescription); } }, { key: 'create', value: _asyncToGenerator(function* () { (0, (_assert2 || _assert()).default)(!this._deleted, 'RemoteDirectory has been deleted'); var created = yield this._getFileSystemService().mkdirp(this._localPath); if (this._subscriptionCount > 0) { this._subscribeToNativeChangeEvents(); } return created; }) }, { key: 'delete', value: _asyncToGenerator(function* () { yield this._getFileSystemService().rmdir(this._localPath); this._handleNativeDeleteEvent(); }) /** * Renames this directory to the given absolute path. */ }, { key: 'rename', value: _asyncToGenerator(function* (newPath) { yield this._getFileSystemService().rename(this._localPath, newPath); // Unsubscribe from the old `this._localPath`. This must be done before // setting the new `this._localPath`. this._unsubscribeFromNativeChangeEvents(); var _default$parse2 = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.parse(this._uri); var protocol = _default$parse2.protocol; var host = _default$parse2.host; this._localPath = newPath; (0, (_assert2 || _assert()).default)(protocol); (0, (_assert2 || _assert()).default)(host); this._uri = protocol + '//' + host + this._localPath; // Subscribe to changes for the new `this._localPath`. This must be done // after setting the new `this._localPath`. if (this._subscriptionCount > 0) { this._subscribeToNativeChangeEvents(); } }) }, { key: 'getEntriesSync', value: function getEntriesSync() { throw new Error('not implemented'); } /* * Calls `callback` with either an Array of entries or an Error if there was a problem fetching * those entries. * * Note: Although this function is `async`, it never rejects. Check whether the `error` argument * passed to `callback` is `null` to determine if there was an error. */ }, { key: 'getEntries', value: _asyncToGenerator(function* (callback) { var _this3 = this; var entries = undefined; try { entries = yield this._getFileSystemService().readdir(this._localPath); } catch (e) { callback(e, null); return; } var directories = []; var files = []; entries.sort(function (a, b) { return a.file.toLowerCase().localeCompare(b.file.toLowerCase()); }).forEach(function (entry) { (0, (_assert2 || _assert()).default)(entry); var uri = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.createRemoteUri(_this3._host, (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.join(_this3._localPath, entry.file)); var symlink = entry.isSymbolicLink; if (entry.stats && entry.stats.isFile()) { files.push(_this3._server.createFile(uri, symlink)); } else { directories.push(_this3._server.createDirectory(uri, _this3._hgRepositoryDescription, symlink)); } }); callback(null, directories.concat(files)); }) }, { key: 'contains', value: function contains(pathToCheck) { if (pathToCheck == null) { return false; } return (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.contains(this.getPath(), pathToCheck); } }, { key: 'off', value: function off() {} // This method is part of the EmitterMixin used by Atom's local Directory, but not documented // as part of the API - https://atom.io/docs/api/latest/Directory, // However, it appears to be called in project.coffee by Atom. // A workaround before Atom 2.0: see ::getHgRepoInfo of main.js. }, { key: 'getHgRepositoryDescription', value: function getHgRepositoryDescription() { return this._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 RemoteDirectory; })(); exports.RemoteDirectory = RemoteDirectory;