diff --git a/spec/project-spec.js b/spec/project-spec.js index 63c065fa6..0f003b26b 100644 --- a/spec/project-spec.js +++ b/spec/project-spec.js @@ -335,9 +335,14 @@ describe('Project', () => { isRoot () { return true } existsSync () { return this.path.endsWith('does-exist') } contains (filePath) { return filePath.startsWith(this.path) } + onDidChangeFiles (callback) { + onDidChangeFilesCallback = callback + return {dispose: () => {}} + } } let serviceDisposable = null + let onDidChangeFilesCallback = null beforeEach(() => { serviceDisposable = atom.packages.serviceHub.provide('atom.directory-provider', '0.1.0', { @@ -349,6 +354,7 @@ describe('Project', () => { } } }) + onDidChangeFilesCallback = null waitsFor(() => atom.project.directoryProviders.length > 0) }) @@ -383,6 +389,28 @@ describe('Project', () => { atom.project.setPaths(['ssh://foreign-directory:8080/does-exist']) expect(atom.project.getDirectories().length).toBe(0) }) + + it('uses the custom onDidChangeFiles as the watcher if available', () => { + // Ensure that all preexisting watchers are stopped + waitsForPromise(() => stopAllWatchers()) + + const remotePath = 'ssh://another-directory:8080/does-exist' + runs(() => atom.project.setPaths([remotePath])) + waitsForPromise(() => atom.project.getWatcherPromise(remotePath)) + + runs(() => { + expect(onDidChangeFilesCallback).not.toBeNull() + + const changeSpy = jasmine.createSpy('atom.project.onDidChangeFiles') + const disposable = atom.project.onDidChangeFiles(changeSpy) + + const events = [{action: 'created', path: remotePath + '/test.txt'}] + onDidChangeFilesCallback(events) + + expect(changeSpy).toHaveBeenCalledWith(events) + disposable.dispose() + }) + }) }) describe('.open(path)', () => { diff --git a/src/project.js b/src/project.js index 48541c395..92a11ec7a 100644 --- a/src/project.js +++ b/src/project.js @@ -338,13 +338,21 @@ class Project extends Model { } this.rootDirectories.push(directory) - this.watcherPromisesByPath[directory.getPath()] = watchPath(directory.getPath(), {}, events => { + + const didChangeCallback = events => { // Stop event delivery immediately on removal of a rootDirectory, even if its watcher // promise has yet to resolve at the time of removal if (this.rootDirectories.includes(directory)) { this.emitter.emit('did-change-files', events) } - }) + } + // We'll use the directory's custom onDidChangeFiles callback, if available. + // CustomDirectory::onDidChangeFiles should match the signature of + // Project::onDidChangeFiles below (although it may resolve asynchronously) + this.watcherPromisesByPath[directory.getPath()] = + directory.onDidChangeFiles != null + ? Promise.resolve(directory.onDidChangeFiles(didChangeCallback)) + : watchPath(directory.getPath(), {}, didChangeCallback) for (let watchedPath in this.watcherPromisesByPath) { if (!this.rootDirectories.find(dir => dir.getPath() === watchedPath)) {