mirror of
https://github.com/atom/atom.git
synced 2026-01-26 15:28:27 -05:00
Async buffer events
This commit is contained in:
@@ -332,7 +332,11 @@ describe "GitRepositoryAsync", ->
|
||||
expect(repo.isStatusNew(repo.getCachedPathStatus(newPath))).toBeTruthy()
|
||||
expect(repo.isStatusModified(repo.getCachedPathStatus(modifiedPath))).toBeTruthy()
|
||||
|
||||
xdescribe "buffer events", ->
|
||||
# This tests the async implementation's events directly, but ultimately I
|
||||
# think we want users to just be able to subscribe to events on GitRepository
|
||||
# and have them bubble up from async-land
|
||||
|
||||
describe "buffer events", ->
|
||||
[editor] = []
|
||||
|
||||
beforeEach ->
|
||||
@@ -345,32 +349,57 @@ describe "GitRepositoryAsync", ->
|
||||
editor.insertNewline()
|
||||
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
atom.project.getRepositories()[0].onDidChangeStatus statusHandler
|
||||
repo = atom.project.getRepositories()[0]
|
||||
repo.async.onDidChangeStatus statusHandler
|
||||
editor.save()
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256}
|
||||
waitsFor ->
|
||||
statusHandler.callCount == 1
|
||||
runs ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256}
|
||||
|
||||
it "emits a status-changed event when a buffer is reloaded", ->
|
||||
fs.writeFileSync(editor.getPath(), 'changed')
|
||||
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
atom.project.getRepositories()[0].onDidChangeStatus statusHandler
|
||||
atom.project.getRepositories()[0].async.onDidChangeStatus statusHandler
|
||||
editor.getBuffer().reload()
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256}
|
||||
editor.getBuffer().reload()
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
reloadHandler = jasmine.createSpy 'reloadHandler'
|
||||
|
||||
waitsFor ->
|
||||
statusHandler.callCount == 1
|
||||
runs ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256}
|
||||
buffer = editor.getBuffer()
|
||||
buffer.onDidReload(reloadHandler)
|
||||
buffer.reload()
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount == 1
|
||||
runs ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
it "emits a status-changed event when a buffer's path changes", ->
|
||||
fs.writeFileSync(editor.getPath(), 'changed')
|
||||
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
atom.project.getRepositories()[0].onDidChangeStatus statusHandler
|
||||
atom.project.getRepositories()[0].async.onDidChangeStatus statusHandler
|
||||
editor.getBuffer().emitter.emit 'did-change-path'
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256}
|
||||
editor.getBuffer().emitter.emit 'did-change-path'
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
waitsFor ->
|
||||
statusHandler.callCount == 1
|
||||
runs ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256}
|
||||
|
||||
pathHandler = jasmine.createSpy('pathHandler')
|
||||
buffer = editor.getBuffer()
|
||||
buffer.onDidChangePath pathHandler
|
||||
buffer.emitter.emit 'did-change-path'
|
||||
waitsFor ->
|
||||
pathHandler.callCount == 1
|
||||
runs ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
it "stops listening to the buffer when the repository is destroyed (regression)", ->
|
||||
atom.project.getRepositories()[0].destroy()
|
||||
|
||||
@@ -13,18 +13,35 @@ const GitUtils = require('git-utils')
|
||||
const _ = require('underscore-plus')
|
||||
|
||||
module.exports = class GitRepositoryAsync {
|
||||
static open (path) {
|
||||
static open (path, options = {}) {
|
||||
// QUESTION: Should this wrap Git.Repository and reject with a nicer message?
|
||||
return new GitRepositoryAsync(path)
|
||||
return new GitRepositoryAsync(path, options)
|
||||
}
|
||||
|
||||
constructor (path) {
|
||||
constructor (path, options) {
|
||||
this.repo = null
|
||||
this.emitter = new Emitter()
|
||||
this.subscriptions = new CompositeDisposable()
|
||||
this.pathStatusCache = {}
|
||||
this._gitUtilsRepo = GitUtils.open(path) // TODO remove after porting ::relativize
|
||||
this.repoPromise = Git.Repository.open(path)
|
||||
|
||||
var {project, refreshOnWindowFocus} = options
|
||||
this.project = project
|
||||
if (refreshOnWindowFocus === undefined) {
|
||||
refreshOnWindowFocus = true
|
||||
}
|
||||
if (refreshOnWindowFocus) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (this.project) {
|
||||
this.subscriptions.add(this.project.onDidAddBuffer((buffer) => {
|
||||
this.subscribeToBuffer(buffer)
|
||||
}))
|
||||
|
||||
this.project.getBuffers().forEach((buffer) => { this.subscribeToBuffer(buffer) })
|
||||
}
|
||||
}
|
||||
|
||||
destroy () {
|
||||
@@ -73,6 +90,7 @@ module.exports = class GitRepositoryAsync {
|
||||
// Returns a Promise that resolves to the status bit of a given path if it has
|
||||
// one, otherwise 'current'.
|
||||
getPathStatus (_path) {
|
||||
console.log('getting path status for', _path)
|
||||
var relativePath = this._gitUtilsRepo.relativize(_path)
|
||||
return this.repoPromise.then((repo) => {
|
||||
return this._filterStatusesByPath(_path)
|
||||
@@ -80,6 +98,7 @@ module.exports = class GitRepositoryAsync {
|
||||
var cachedStatus = this.pathStatusCache[relativePath] || 0
|
||||
var status = statuses[0] ? statuses[0].statusBit() : Git.Status.STATUS.CURRENT
|
||||
if (status !== cachedStatus) {
|
||||
console.log('async emitting', {path: _path, pathStatus: status})
|
||||
this.emitter.emit('did-change-status', {path: _path, pathStatus: status})
|
||||
}
|
||||
this.pathStatusCache[relativePath] = status
|
||||
@@ -134,8 +153,37 @@ module.exports = class GitRepositoryAsync {
|
||||
})
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
// =================
|
||||
// Section: Private
|
||||
// ================
|
||||
|
||||
subscribeToBuffer (buffer) {
|
||||
var getBufferPathStatus = () => {
|
||||
var _path = buffer.getPath()
|
||||
var bufferSubscriptions = new CompositeDisposable()
|
||||
|
||||
if (_path) {
|
||||
// We don't need to do anything with this promise, we just want the
|
||||
// emitted event side effect
|
||||
this.getPathStatus(_path)
|
||||
}
|
||||
|
||||
bufferSubscriptions.add(
|
||||
buffer.onDidSave(getBufferPathStatus),
|
||||
buffer.onDidReload(getBufferPathStatus),
|
||||
buffer.onDidChangePath(getBufferPathStatus)
|
||||
)
|
||||
|
||||
bufferSubscriptions.add(() => {
|
||||
buffer.onDidDestroy(() => {
|
||||
bufferSubscriptions.dispose()
|
||||
this.subscriptions.remove(bufferSubscriptions)
|
||||
})
|
||||
})
|
||||
|
||||
this.subscriptions.add(bufferSubscriptions)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
getCachedPathStatus (_path) {
|
||||
return this.pathStatusCache[this._gitUtilsRepo.relativize(_path)]
|
||||
|
||||
@@ -76,7 +76,7 @@ class GitRepository
|
||||
unless @repo?
|
||||
throw new Error("No Git repository found searching path: #{path}")
|
||||
|
||||
@async = GitRepositoryAsync.open(path)
|
||||
@async = GitRepositoryAsync.open(path, options)
|
||||
|
||||
@statuses = {}
|
||||
@upstream = {ahead: 0, behind: 0}
|
||||
@@ -319,6 +319,9 @@ class GitRepository
|
||||
# Returns a {Number} representing the status. This value can be passed to
|
||||
# {::isStatusModified} or {::isStatusNew} to get more information.
|
||||
getPathStatus: (path) ->
|
||||
# Trigger events emitted on the async repo as well
|
||||
@async.getPathStatus(path)
|
||||
|
||||
repo = @getRepo(path)
|
||||
relativePath = @relativize(path)
|
||||
currentPathStatus = @statuses[relativePath] ? 0
|
||||
@@ -479,6 +482,7 @@ class GitRepository
|
||||
# Refreshes the current git status in an outside process and asynchronously
|
||||
# updates the relevant properties.
|
||||
refreshStatus: ->
|
||||
@async.refreshStatus()
|
||||
@handlerPath ?= require.resolve('./repository-status-handler')
|
||||
|
||||
@statusTask?.terminate()
|
||||
|
||||
Reference in New Issue
Block a user