Don't create duplicate buffers if a path is opened twice concurrently

This commit is contained in:
Max Brunsfeld
2017-05-23 07:27:56 -07:00
parent ccdbfda0bc
commit 2c2d00a403
2 changed files with 29 additions and 2 deletions

View File

@@ -1,4 +1,5 @@
temp = require('temp').track()
TextBuffer = require('text-buffer')
Project = require '../src/project'
fs = require 'fs-plus'
path = require 'path'
@@ -326,7 +327,8 @@ describe "Project", ->
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
describe ".bufferForPath(path)", ->
[buffer] = []
buffer = null
beforeEach ->
waitsForPromise ->
atom.project.bufferForPath("a").then (o) ->
@@ -346,6 +348,23 @@ describe "Project", ->
atom.project.bufferForPath("b").then (anotherBuffer) ->
expect(anotherBuffer).not.toBe buffer
waitsForPromise ->
Promise.all([
atom.project.bufferForPath('c'),
atom.project.bufferForPath('c')
]).then ([buffer1, buffer2]) ->
expect(buffer1).toBe(buffer2)
it "retries loading the buffer if it previously failed", ->
waitsForPromise shouldReject: true, ->
spyOn(TextBuffer, 'load').andCallFake ->
Promise.reject(new Error('Could not open file'))
atom.project.bufferForPath('b')
waitsForPromise shouldReject: false, ->
TextBuffer.load.andCallThrough()
atom.project.bufferForPath('b')
it "creates a new buffer if the previous buffer was destroyed", ->
buffer.release()

View File

@@ -27,6 +27,7 @@ class Project extends Model
@defaultDirectoryProvider = new DefaultDirectoryProvider()
@repositoryPromisesByPath = new Map()
@repositoryProviders = [new GitRepositoryProvider(this, config)]
@loadPromisesByPath = {}
@consumeServices(packageManager)
destroyed: ->
@@ -42,6 +43,7 @@ class Project extends Model
buffer?.destroy() for buffer in @buffers
@buffers = []
@setPaths([])
@loadPromisesByPath = {}
@consumeServices(packageManager)
destroyUnretainedBuffers: ->
@@ -381,13 +383,19 @@ class Project extends Model
buildBuffer: (absoluteFilePath) ->
params = {shouldDestroyOnFileDelete: @shouldDestroyBufferOnFileDelete}
if absoluteFilePath?
promise = TextBuffer.load(absoluteFilePath, params)
promise =
@loadPromisesByPath[absoluteFilePath] ?=
TextBuffer.load(absoluteFilePath, params).catch (error) =>
delete @loadPromisesByPath[absoluteFilePath]
throw error
else
promise = Promise.resolve(new TextBuffer(params))
promise.then (buffer) =>
delete @loadPromisesByPath[absoluteFilePath]
@addBuffer(buffer)
buffer
addBuffer: (buffer, options={}) ->
@addBufferAtIndex(buffer, @buffers.length, options)