From ada992be4d8a6a45c4a93fddc5c65f46dd28bc01 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 11:14:56 -0800 Subject: [PATCH 01/49] Upgrade to telepath@0.29.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d03b8a38..08edd5108 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.23.0", + "telepath": "0.29.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, From 62feefd28d66819ada5078e33b65ec1073e4c864 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 11:15:15 -0800 Subject: [PATCH 02/49] Upgrade to emissary@0.15.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 08edd5108..ffb0b5742 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "clear-cut": "0.1.0", "coffee-script": "1.6.3", "coffeestack": "0.6.0", - "emissary": "0.9.0", + "emissary": "0.15.0", "first-mate": "0.5.0", "fs-plus": "0.9.0", "fuzzaldrin": "0.1.0", From 1808e5f991f10e16f0c957a46afc2625ce6a9f1c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 16:33:26 -0800 Subject: [PATCH 03/49] Initial :hocho: at extending telepath.Model in Project/TextBuffer --- package.json | 2 +- src/atom.coffee | 8 ++-- src/edit-session.coffee | 2 +- src/project.coffee | 95 +++++++++++------------------------------ src/text-buffer.coffee | 53 +++++------------------ src/window.coffee | 2 +- 6 files changed, 42 insertions(+), 120 deletions(-) diff --git a/package.json b/package.json index ffb0b5742..3ceaacd91 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.29.0", + "telepath": "0.31.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, diff --git a/src/atom.coffee b/src/atom.coffee index 2dfc70a68..ea82b5705 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -121,10 +121,10 @@ class Atom deserializeProject: -> Project = require './project' state = @getWindowState() - @project = deserialize(state.get('project')) + @project = state.get('project') unless @project? - @project = new Project(@getLoadSettings().initialPath) - state.set('project', @project.getState()) + @project = new Project(path: @getLoadSettings().initialPath) + state.set('project', @project) deserializeRootView: -> RootView = require './root-view' @@ -295,6 +295,8 @@ class Atom doc = Document.deserialize(documentState) if documentState? doc ?= Document.create() + doc.registerModelClass(require('./project')) + doc.registerModelClass(require('./text-buffer')) # TODO: Remove this when everything is using telepath models if @site? @site.setRootDocument(doc) diff --git a/src/edit-session.coffee b/src/edit-session.coffee index a3bb2673c..8970e14d2 100644 --- a/src/edit-session.coffee +++ b/src/edit-session.coffee @@ -139,10 +139,10 @@ class EditSession @destroyed = true @unsubscribe() selection.destroy() for selection in @getSelections() - @buffer.release() @displayBuffer.destroy() @languageMode.destroy() project?.removeEditSession(this) + @buffer.release() @emit 'destroyed' @off() diff --git a/src/project.coffee b/src/project.coffee index 8357c452f..f5d45f9cb 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -5,7 +5,7 @@ _ = require 'underscore-plus' fs = require 'fs-plus' Q = require 'q' telepath = require 'telepath' -{Range} = telepath +{Model, Range} = telepath TextBuffer = require './text-buffer' EditSession = require './edit-session' @@ -19,16 +19,12 @@ Git = require './git' # Ultimately, a project is a git directory that's been opened. It's a collection # of directories and files that you can operate on. module.exports = -class Project +class Project extends Model Emitter.includeInto(this) - @acceptsDocuments: true - @version: 1 - - registerDeserializer(this) - - # Private: - @deserialize: (state) -> new Project(state) + @properties + buffers: [] + path: null # Public: Find the local path for the given repository URL. @pathForRepositoryUrl: (repoUrl) -> @@ -36,10 +32,11 @@ class Project repoName = repoName.replace(/\.git$/, '') path.join(atom.config.get('core.projectHome'), repoName) - rootDirectory: null - editSessions: null - ignoredPathRegexes: null - openers: null + # Private: + attached: -> + @openers = [] + @editSessions = [] + @setPath(@path) # Public: registerOpener: (opener) -> @openers.push(opener) @@ -59,51 +56,10 @@ class Project @repo.destroy() @repo = null - # Public: Establishes a new project at a given path. - # - # path - The {String} name of the path - constructor: (pathOrState) -> - @openers = [] - @editSessions = [] - @buffers = [] - - if pathOrState instanceof telepath.Document - @state = pathOrState - if projectPath = @state.remove('path') - @setPath(projectPath) - else - @setPath(@constructor.pathForRepositoryUrl(@state.get('repoUrl'))) - - @state.get('buffers').each (bufferState) => - if buffer = deserialize(bufferState, project: this) - @addBuffer(buffer, updateState: false) - else - @state = atom.site.createDocument(deserializer: @constructor.name, version: @constructor.version, buffers: []) - @setPath(pathOrState) - - @state.get('buffers').on 'changed', ({index, insertedValues, removedValues, siteId}) => - return if siteId is @state.siteId - - for removedBuffer in removedValues - @removeBufferAtIndex(index, updateState: false) - for insertedBuffer, i in insertedValues - @addBufferAtIndex(deserialize(insertedBuffer, project: this), index + i, updateState: false) - - # Private: - serialize: -> - state = @state.clone() - state.set('path', @getPath()) - @destroyUnretainedBuffers() - state.set('buffers', buffer.serialize() for buffer in @getBuffers()) - state - # Private: destroyUnretainedBuffers: -> buffer.destroy() for buffer in @getBuffers() when not buffer.isRetained() - # Public: ? - getState: -> @state - # Public: Returns the {Git} repository if available. getRepo: -> @repo @@ -223,17 +179,15 @@ class Project new Array(@buffers...) isPathModified: (filePath) -> - absoluteFilePath = @resolve(filePath) - existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath - existingBuffer?.isModified() + @findBufferForPath(@resolve(filePath))?.isModified() + + findBufferForPath: (filePath) -> + _.find @buffers.getValues(), (buffer) -> buffer.getPath() == filePath # Private: Only to be used in specs bufferForPathSync: (filePath) -> absoluteFilePath = @resolve(filePath) - - if filePath - existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath - + existingBuffer = @findBufferForPath(absoluteFilePath) if filePath existingBuffer ? @buildBufferSync(absoluteFilePath) # Private: Given a file path, this retrieves or creates a new {TextBuffer}. @@ -246,9 +200,7 @@ class Project # Returns a promise that resolves to the {TextBuffer}. bufferForPath: (filePath) -> absoluteFilePath = @resolve(filePath) - if absoluteFilePath - existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath - + existingBuffer = @findBufferForPath(absoluteFilePath) if absoluteFilePath Q(existingBuffer ? @buildBuffer(absoluteFilePath)) # Private: @@ -269,10 +221,11 @@ class Project # # Returns a promise that resolves to the {TextBuffer}. buildBuffer: (absoluteFilePath) -> - buffer = new TextBuffer({project: this, filePath: absoluteFilePath}) - buffer.load().then (buffer) => - @addBuffer(buffer) - buffer + buffer = new TextBuffer({filePath: absoluteFilePath}) + @addBuffer(buffer) + buffer.load() + .then((buffer) -> buffer) + .catch(=> @removeBuffer(buffer)) # Private: addBuffer: (buffer, options={}) -> @@ -280,8 +233,7 @@ class Project # Private: addBufferAtIndex: (buffer, index, options={}) -> - @buffers[index] = buffer - @state.get('buffers').insert(index, buffer.getState()) if options.updateState ? true + @buffers.insert(index, buffer) @emit 'buffer-created', buffer # Private: Removes a {TextBuffer} association from the project. @@ -293,8 +245,9 @@ class Project # Private: removeBufferAtIndex: (index, options={}) -> + console.log 'removing buffer', index + console.trace() [buffer] = @buffers.splice(index, 1) - @state.get('buffers')?.remove(index) if options.updateState ? true buffer?.destroy() # Public: Performs a search across all the files in the project. diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index a37e8e0fa..34cf3dbbd 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -1,4 +1,3 @@ -crypto = require 'crypto' {Emitter, Subscriber} = require 'emissary' guid = require 'guid' Q = require 'q' @@ -8,25 +7,23 @@ telepath = require 'telepath' _ = require 'underscore-plus' File = require './file' -{Point, Range} = telepath +{Point, Range, Model} = telepath # Private: Represents the contents of a file. # # The `Buffer` is often associated with a {File}. However, this is not always # the case, as a `Buffer` could be an unsaved chunk of text. module.exports = -class TextBuffer +class TextBuffer extends Model Emitter.includeInto(this) Subscriber.includeInto(this) - @acceptsDocuments: true - @version: 2 - registerDeserializer(this) + @properties + text: -> new telepath.String('', replicated: false) + id: -> guid.create().toString() + filePath: null - @deserialize: (state, params) -> - buffer = new this(state, params) - buffer.load() - buffer + @::lazyGetter 'project', -> @grandparent stoppedChangingDelay: 300 stoppedChangingTimeout: null @@ -36,34 +33,14 @@ class TextBuffer file: null refcount: 0 - # Creates a new buffer. - # - # * optionsOrState - An {Object} or a telepath.Document - # + filePath - A {String} representing the file path - constructor: (optionsOrState={}, params={}) -> - if optionsOrState instanceof telepath.Document - {@project} = params - @state = optionsOrState - @id = @state.get('id') - filePath = @state.get('relativePath') - @text = @state.get('text') - @useSerializedText = @state.get('isModified') != false - else - {@project, filePath} = optionsOrState - @text = new telepath.String(initialText ? '', replicated: false) - @id = guid.create().toString() - @state = atom.site.createDocument - id: @id - deserializer: @constructor.name - version: @constructor.version - text: @text - + attached: -> @loaded = false + @subscribe @text, 'changed', @handleTextChange @subscribe @text, 'marker-created', (marker) => @emit 'marker-created', marker @subscribe @text, 'markers-updated', => @emit 'markers-updated' - @setPath(@project.resolve(filePath)) if @project + @setPath(@project.resolve(@filePath)) if @project loadSync: -> @updateCachedDiskContentsSync() @@ -109,16 +86,6 @@ class TextBuffer @destroy() unless @isRetained() this - serialize: -> - state = @state.clone() - state.set('isModified', @isModified()) - state.set('diskContentsDigest', @file.getDigest()) if @file - for marker in state.get('text').getMarkers() when marker.isRemote() - marker.destroy() - state - - getState: -> @state - subscribeToFile: -> @file.on "contents-changed", => @conflict = true if @isModified() diff --git a/src/window.coffee b/src/window.coffee index 6be8a3e9d..8c955662a 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -69,7 +69,7 @@ window.startEditorWindow = -> window.unloadEditorWindow = -> return if not atom.project and not atom.rootView windowState = atom.getWindowState() - windowState.set('project', atom.project.serialize()) + windowState.set('project', atom.project) windowState.set('syntax', atom.syntax.serialize()) windowState.set('rootView', atom.rootView.serialize()) atom.packages.deactivatePackages() From ffc936ca4dc04effffb3dac7eaa4622ad38979e2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 17:17:54 -0800 Subject: [PATCH 04/49] Use telepath.Document::registerModelClasses --- package.json | 2 +- src/atom.coffee | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3ceaacd91..5082a196f 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.31.0", + "telepath": "0.32.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, diff --git a/src/atom.coffee b/src/atom.coffee index ea82b5705..7ae64877a 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -295,8 +295,7 @@ class Atom doc = Document.deserialize(documentState) if documentState? doc ?= Document.create() - doc.registerModelClass(require('./project')) - doc.registerModelClass(require('./text-buffer')) + doc.registerModelClasses(require('./project'), require('./text-buffer')) # TODO: Remove this when everything is using telepath models if @site? @site.setRootDocument(doc) From 913bb82d6ed902f0271f12e0eea0c6c7ee7ca7b9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 17:33:40 -0800 Subject: [PATCH 05/49] Remove debug logging --- src/project.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index f5d45f9cb..a324e1588 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -245,8 +245,6 @@ class Project extends Model # Private: removeBufferAtIndex: (index, options={}) -> - console.log 'removing buffer', index - console.trace() [buffer] = @buffers.splice(index, 1) buffer?.destroy() From 6290c19264125710661681d67892ec5be4b0cafa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 17:34:13 -0800 Subject: [PATCH 06/49] Set up spec Project as telepath model --- spec/spec-helper.coffee | 6 ++---- src/project.coffee | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index ffc2bdba8..0c381bf6a 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -47,10 +47,8 @@ if specDirectory = atom.getLoadSettings().specDirectory beforeEach -> $.fx.off = true - if specProjectPath - atom.project = new Project(specProjectPath) - else - atom.project = new Project(path.join(@specDirectory, 'fixtures')) + projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures') + atom.project = atom.getWindowState().set('project', new Project(path: projectPath)) window.project = atom.project window.resetTimeouts() diff --git a/src/project.coffee b/src/project.coffee index a324e1588..8f9ae40c3 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -209,9 +209,9 @@ class Project extends Model # Private: DEPRECATED buildBufferSync: (absoluteFilePath) -> - buffer = new TextBuffer({project: this, filePath: absoluteFilePath}) - buffer.loadSync() + buffer = new TextBuffer({filePath: absoluteFilePath}) @addBuffer(buffer) + buffer.loadSync() buffer # Private: Given a file path, this sets its {TextBuffer}. From fe9f1373c1d9873488ba4e6e7018bf13dd55560d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 17:41:30 -0800 Subject: [PATCH 07/49] Cancel stopped changing timeout when destroyed --- src/text-buffer.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 34cf3dbbd..1ab751320 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -69,6 +69,7 @@ class TextBuffer extends Model destroy: -> unless @destroyed + @cancelStoppedChangingTimeout() @file?.off() @unsubscribe() @destroyed = true @@ -647,8 +648,11 @@ class TextBuffer extends Model else text - scheduleModifiedEvents: -> + cancelStoppedChangingTimeout: -> clearTimeout(@stoppedChangingTimeout) if @stoppedChangingTimeout + + scheduleModifiedEvents: -> + @cancelStoppedChangingTimeout() stoppedChangingCallback = => @stoppedChangingTimeout = null modifiedStatus = @isModified() From 957374eb4027d8e1ea3239911dececdf17e87584 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 18:13:51 -0800 Subject: [PATCH 08/49] Call telepath.Array::getValues() during clone --- src/project.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index 8f9ae40c3..d8c0f74c7 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -176,7 +176,7 @@ class Project extends Model # # Returns an {Array} of {TextBuffer}s. getBuffers: -> - new Array(@buffers...) + new Array(@buffers.getValues()...) isPathModified: (filePath) -> @findBufferForPath(@resolve(filePath))?.isModified() From 276e63611a2756dae47568c7dffde934b13bc753 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 18:30:42 -0800 Subject: [PATCH 09/49] Register buffer with project --- spec/text-buffer-spec.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index 3c0a425a1..c28c5cd74 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -311,8 +311,8 @@ describe 'TextBuffer', -> it "returns false until the buffer is fully loaded", -> buffer.release() - filePath = temp.openSync('atom').path - buffer = new TextBuffer({project, filePath}) + buffer = new TextBuffer({filePath: temp.openSync('atom').path}) + project.addBuffer(buffer) expect(buffer.isModified()).toBeFalsy() From 11787e5a5d1444756a1b70ec0ebb857e513ec7a6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 18:45:08 -0800 Subject: [PATCH 10/49] Return added buffer from Project::addBufferAtIndex --- src/project.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index d8c0f74c7..a3e799922 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -233,8 +233,9 @@ class Project extends Model # Private: addBufferAtIndex: (buffer, index, options={}) -> - @buffers.insert(index, buffer) + buffer = @buffers.insert(index, buffer) @emit 'buffer-created', buffer + buffer # Private: Removes a {TextBuffer} association from the project. # From 4bb21fd9eca999ae206f382288db051075cd17fa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 18:45:42 -0800 Subject: [PATCH 11/49] Use project.addBuffer instead of window.deserialize --- spec/text-buffer-spec.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index c28c5cd74..bbafba113 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -935,13 +935,13 @@ describe 'TextBuffer', -> it "loads the current contents of the file at the serialized path", -> expect(buffer.isModified()).toBeFalsy() - state = buffer.serialize() + state = buffer.getState().clone() state.get('text').insertTextAtPoint([0, 0], 'simulate divergence of on-disk contents from serialized contents') - buffer2 = deserialize(state, {project}) + buffer2 = project.addBuffer(new TextBuffer(state)) - waitsFor -> - buffer2.cachedDiskContents + waitsForPromise -> + buffer2.load() runs -> expect(buffer2.isModified()).toBeFalsy() From b12954760d8f2db5abb862715734519ffec37be0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 19:01:26 -0800 Subject: [PATCH 12/49] Use Project::addBuffer instead of ::openSync --- spec/text-buffer-spec.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index bbafba113..c8a408e7e 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -955,14 +955,14 @@ describe 'TextBuffer', -> filePath = temp.openSync('atom').path fs.writeFileSync(filePath, "words") - {buffer} = project.openSync(filePath) + buffer = project.addBuffer(new TextBuffer({filePath})) buffer.setText("BUFFER CHANGE") - state = buffer.serialize() + state = buffer.getState().clone() expect(state.getObject('text')).toBe 'BUFFER CHANGE' fs.writeFileSync(filePath, "DISK CHANGE") - buffer2 = deserialize(state, {project}) + buffer2 = project.addBuffer(new TextBuffer(state)) waitsFor -> buffer2.cachedDiskContents From 7dd84636ba3784656fdd01ab19853c651f789904 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 12 Nov 2013 19:01:58 -0800 Subject: [PATCH 13/49] Use Project::addBuffer instead of window.deserialize --- spec/text-buffer-spec.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index c8a408e7e..a794a48d8 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -977,13 +977,13 @@ describe 'TextBuffer', -> previousText = buffer.getText() buffer.setText("abc") - state = buffer.serialize() + state = buffer.getState().clone() expect(state.getObject('text')).toBe 'abc' - buffer2 = deserialize(state, {project}) + buffer2 = project.addBuffer(new TextBuffer(state)) - waitsFor -> - buffer2.cachedDiskContents + waitsForPromise -> + buffer2.load() runs -> expect(buffer2.getPath()).toBe(buffer.getPath()) @@ -999,10 +999,10 @@ describe 'TextBuffer', -> buffer = project.bufferForPathSync() buffer.setText("abc") - state = buffer.serialize() + state = buffer.getState().clone() expect(state.get('path')).toBeUndefined() expect(state.getObject('text')).toBe 'abc' - buffer2 = deserialize(state) + buffer2 = project.addBuffer(new TextBuffer(state)) expect(buffer2.getPath()).toBeUndefined() expect(buffer2.getText()).toBe("abc") From 6caed6e9181e03a60774f7c32953024e3f97f28f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 09:01:23 -0800 Subject: [PATCH 14/49] Add model property for relative path --- src/text-buffer.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 1ab751320..c77bfb337 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -22,6 +22,7 @@ class TextBuffer extends Model text: -> new telepath.String('', replicated: false) id: -> guid.create().toString() filePath: null + relativePath: null @::lazyGetter 'project', -> @grandparent @@ -108,7 +109,7 @@ class TextBuffer extends Model @emitModifiedStatusChanged(@isModified()) @file.on "moved", => - @state.set('relativePath', @project.relativize(@getPath())) + @relativePath = @project.relativize(@getPath()) @emit "path-changed", this ### Public ### @@ -154,7 +155,7 @@ class TextBuffer extends Model @getRelativePath() getRelativePath: -> - @state.get('relativePath') + @relativePath # Sets the path for the file. # @@ -170,7 +171,7 @@ class TextBuffer extends Model else @file = null - @state.set('relativePath', @project.relativize(path)) + @relativePath = @project.relativize(path) @emit "path-changed", this # Retrieves the current buffer's file extension. From 21e0e95a7ac42d632fabf309bfb5e771e7ce80fb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 09:07:14 -0800 Subject: [PATCH 15/49] Add model property for disk contents digest --- src/text-buffer.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index c77bfb337..0e875d8ec 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -23,6 +23,7 @@ class TextBuffer extends Model id: -> guid.create().toString() filePath: null relativePath: null + diskContentsDigest: null @::lazyGetter 'project', -> @grandparent @@ -52,7 +53,7 @@ class TextBuffer extends Model finishLoading: -> @loaded = true - if @useSerializedText and @state.get('diskContentsDigest') == @file?.getDigest() + if @useSerializedText and @diskContentsDigest is @file?.getDigest() @emitModifiedStatusChanged(true) else @reload() From df3fe90c890caa8cc730ef7aa35a222b79c9424e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 17:01:12 -0800 Subject: [PATCH 16/49] Upgrade to telepath@0.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5082a196f..25c90b762 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.32.0", + "telepath": "0.33.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, From 055ec8cb9c62761c657451000d504617daef2772 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 17:12:24 -0800 Subject: [PATCH 17/49] Implement beforePersistence in TextBuffer --- spec/text-buffer-spec.coffee | 3 +++ src/text-buffer.coffee | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index a794a48d8..9bc13b70c 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -935,6 +935,7 @@ describe 'TextBuffer', -> it "loads the current contents of the file at the serialized path", -> expect(buffer.isModified()).toBeFalsy() + buffer.getState().serializeForPersistence() state = buffer.getState().clone() state.get('text').insertTextAtPoint([0, 0], 'simulate divergence of on-disk contents from serialized contents') @@ -958,6 +959,7 @@ describe 'TextBuffer', -> buffer = project.addBuffer(new TextBuffer({filePath})) buffer.setText("BUFFER CHANGE") + buffer.getState().serializeForPersistence() state = buffer.getState().clone() expect(state.getObject('text')).toBe 'BUFFER CHANGE' fs.writeFileSync(filePath, "DISK CHANGE") @@ -977,6 +979,7 @@ describe 'TextBuffer', -> previousText = buffer.getText() buffer.setText("abc") + buffer.getState().serializeForPersistence() state = buffer.getState().clone() expect(state.getObject('text')).toBe 'abc' diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 0e875d8ec..d4b4f8beb 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -24,6 +24,8 @@ class TextBuffer extends Model filePath: null relativePath: null diskContentsDigest: null + modifiedWhenLastPersisted: false + digestWhenLastPersisted: null @::lazyGetter 'project', -> @grandparent @@ -35,8 +37,10 @@ class TextBuffer extends Model file: null refcount: 0 + # Private: Called by telepath attached: -> @loaded = false + @useSerializedText = @modifiedWhenLastPersisted != false @subscribe @text, 'changed', @handleTextChange @subscribe @text, 'marker-created', (marker) => @emit 'marker-created', marker @@ -44,6 +48,11 @@ class TextBuffer extends Model @setPath(@project.resolve(@filePath)) if @project + # Private: Called by telepath + beforePersistence: -> + @modifiedWhenLastPersisted = @isModified() + @digestWhenLastPersisted = @file?.getDigest() + loadSync: -> @updateCachedDiskContentsSync() @finishLoading() @@ -53,7 +62,7 @@ class TextBuffer extends Model finishLoading: -> @loaded = true - if @useSerializedText and @diskContentsDigest is @file?.getDigest() + if @useSerializedText and @digestWhenLastPersisted is @file?.getDigest() @emitModifiedStatusChanged(true) else @reload() From 618d281d6c7ed3906716ee874462bf38943c2725 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 17:13:12 -0800 Subject: [PATCH 18/49] Restore buffer.release() call to previously location --- src/edit-session.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edit-session.coffee b/src/edit-session.coffee index 8970e14d2..a3bb2673c 100644 --- a/src/edit-session.coffee +++ b/src/edit-session.coffee @@ -139,10 +139,10 @@ class EditSession @destroyed = true @unsubscribe() selection.destroy() for selection in @getSelections() + @buffer.release() @displayBuffer.destroy() @languageMode.destroy() project?.removeEditSession(this) - @buffer.release() @emit 'destroyed' @off() From 5fdec4dc7b3952e280e07c7e092c5bc062ed38ca Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 17:49:53 -0800 Subject: [PATCH 19/49] Move checkoutHead implementation to Editor --- src/editor.coffee | 6 ++++-- src/text-buffer.coffee | 6 ------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index db11812fe..f75c84cf7 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -586,8 +586,10 @@ class Editor extends View @showIndentGuide = showIndentGuide @resetDisplay() - # {Delegates to: TextBuffer.checkoutHead} - checkoutHead: -> @getBuffer().checkoutHead() + # Checkout the HEAD revision of this editor's file. + checkoutHead: -> + if path = @getPath() + @project.getRepo()?.checkoutHead(path) # {Delegates to: EditSession.setText} setText: (text) -> @activeEditSession.setText(text) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index d4b4f8beb..9ebcd48e8 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -632,12 +632,6 @@ class TextBuffer extends Model return match[0][0] != '\t' undefined - # Checks out the current `HEAD` revision of the file. - checkoutHead: -> - path = @getPath() - return unless path - @project.getRepo()?.checkoutHead(path) - ### Internal ### transact: (fn) -> @text.transact fn From dc7e7f9ed08ec641832c870a5664b9bef3a130dd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 17:51:13 -0800 Subject: [PATCH 20/49] Listen for buffer destroyed in Project --- src/project.coffee | 1 + src/text-buffer.coffee | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index a3e799922..8484736d1 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -234,6 +234,7 @@ class Project extends Model # Private: addBufferAtIndex: (buffer, index, options={}) -> buffer = @buffers.insert(index, buffer) + buffer.once 'destroyed', => @removeBuffer(buffer) @emit 'buffer-created', buffer buffer diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 9ebcd48e8..26f69209d 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -84,7 +84,6 @@ class TextBuffer extends Model @file?.off() @unsubscribe() @destroyed = true - @project?.removeBuffer(this) @emit 'destroyed' isRetained: -> @refcount > 0 From abc1f23516674c85a4245d1d78016aed36fcfb9c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 18:03:10 -0800 Subject: [PATCH 21/49] Remove unused relative path from Editor/EditSession/TextBuffer --- src/edit-session.coffee | 3 --- src/editor.coffee | 3 --- src/text-buffer.coffee | 11 ++--------- src/tokenized-buffer.coffee | 4 ++-- 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/edit-session.coffee b/src/edit-session.coffee index a3bb2673c..42c08c5ff 100644 --- a/src/edit-session.coffee +++ b/src/edit-session.coffee @@ -335,9 +335,6 @@ class EditSession # {Delegates to: TextBuffer.getPath} getPath: -> @buffer.getPath() - # {Delegates to: TextBuffer.getRelativePath} - getRelativePath: -> @buffer.getRelativePath() - # {Delegates to: TextBuffer.getText} getText: -> @buffer.getText() diff --git a/src/editor.coffee b/src/editor.coffee index f75c84cf7..e236ca41c 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -600,9 +600,6 @@ class Editor extends View # {Delegates to: EditSession.getPath} getPath: -> @activeEditSession?.getPath() - # {Delegates to: EditSession.getRelativePath} - getRelativePath: -> @activeEditSession?.getRelativePath() - # {Delegates to: TextBuffer.getLineCount} getLineCount: -> @getBuffer().getLineCount() diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 26f69209d..1fba092b2 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -27,8 +27,6 @@ class TextBuffer extends Model modifiedWhenLastPersisted: false digestWhenLastPersisted: null - @::lazyGetter 'project', -> @grandparent - stoppedChangingDelay: 300 stoppedChangingTimeout: null cachedDiskContents: null @@ -46,7 +44,7 @@ class TextBuffer extends Model @subscribe @text, 'marker-created', (marker) => @emit 'marker-created', marker @subscribe @text, 'markers-updated', => @emit 'markers-updated' - @setPath(@project.resolve(@filePath)) if @project + @setPath(@filePath) # Private: Called by telepath beforePersistence: -> @@ -118,7 +116,6 @@ class TextBuffer extends Model @emitModifiedStatusChanged(@isModified()) @file.on "moved", => - @relativePath = @project.relativize(@getPath()) @emit "path-changed", this ### Public ### @@ -161,10 +158,7 @@ class TextBuffer extends Model @file?.getPath() getUri: -> - @getRelativePath() - - getRelativePath: -> - @relativePath + @getPath() # Sets the path for the file. # @@ -180,7 +174,6 @@ class TextBuffer extends Model else @file = null - @relativePath = @project.relativize(path) @emit "path-changed", this # Retrieves the current buffer's file extension. diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 4dc775496..7b1ca378d 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -36,7 +36,7 @@ class TokenizedBuffer { @buffer, tabLength } = optionsOrState @state = atom.site.createDocument deserializer: @constructor.name - bufferPath: @buffer.getRelativePath() + bufferPath: @buffer.getPath() tabLength: tabLength ? atom.config.get('editor.tabLength') ? 2 @subscribe syntax, 'grammar-added grammar-updated', (grammar) => @@ -48,7 +48,7 @@ class TokenizedBuffer @on 'grammar-changed grammar-updated', => @resetTokenizedLines() @subscribe @buffer, "changed", (e) => @handleBufferChange(e) - @subscribe @buffer, "path-changed", => @state.set('bufferPath', @buffer.getRelativePath()) + @subscribe @buffer, "path-changed", => @state.set('bufferPath', @buffer.getPath()) @reloadGrammar() From a475e27cd4a55425ec73596243c625703e7752e3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 13 Nov 2013 18:51:51 -0800 Subject: [PATCH 22/49] Call createAsRoot for mini editor's buffer --- package.json | 2 +- src/editor.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 25c90b762..7a26e8b88 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.33.0", + "telepath": "0.34.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, diff --git a/src/editor.coffee b/src/editor.coffee index e236ca41c..4b3fdb8a1 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -104,7 +104,7 @@ class Editor extends View @edit(editSession) else if @mini @edit(new EditSession - buffer: new TextBuffer + buffer: TextBuffer.createAsRoot() softWrap: false tabLength: 2 softTabs: true From 34f1472653c90a924b97f50bda90616fb613ce09 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 08:52:19 -0800 Subject: [PATCH 23/49] Use getValues() when iterating over buffers --- src/project.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index 8484736d1..d11a832e6 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -282,7 +282,7 @@ class Project extends Model task.on 'scan:paths-searched', (numberOfPathsSearched) -> options.onPathsSearched(numberOfPathsSearched) - for buffer in @buffers when buffer.isModified() + for buffer in @buffers.getValues() when buffer.isModified() filePath = buffer.getPath() matches = [] buffer.scan regex, (match) -> matches.push match From cf0bdb9c94b1d121f3a977b679507f5a6d701445 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 11:12:53 -0800 Subject: [PATCH 24/49] Remove unused property --- src/text-buffer.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 1fba092b2..49997859e 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -23,7 +23,6 @@ class TextBuffer extends Model id: -> guid.create().toString() filePath: null relativePath: null - diskContentsDigest: null modifiedWhenLastPersisted: false digestWhenLastPersisted: null From 6432cda6911c12cbb59255f331f794b01cb1029d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:20:12 -0800 Subject: [PATCH 25/49] Upgrade to telepath@0.35.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a26e8b88..100d3a727 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.34.0", + "telepath": "0.35.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, From 8b17b7eca95423a60b0a6c1d4d35ae072d49beb1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:20:41 -0800 Subject: [PATCH 26/49] Remove unused repoUrl property --- src/project.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index d11a832e6..c76b3f0ca 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -81,9 +81,6 @@ class Project extends Model else @rootDirectory = null - if originUrl = @repo?.getOriginUrl() - @state.set('repoUrl', originUrl) - @emit "path-changed" # Public: Returns the name of the root directory. From 7b43c8a86007cd0a76057660c7b621a8642cf824 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:37:22 -0800 Subject: [PATCH 27/49] Use Atom::replicate in git spec to simulate project serialization --- spec/git-spec.coffee | 3 ++- src/atom.coffee | 4 ++++ src/git.coffee | 3 +-- src/text-buffer.coffee | 7 +++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index 4893dbfd1..827643197 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -257,7 +257,8 @@ describe "Git", -> it "subscribes to all the serialized buffers in the project", -> project.openSync('sample.js') - project2 = deserialize(project.serialize()) + #TODO Replace with atom.replicate().project when Atom is a telepath model + project2 = atom.replicate().get('project') buffer = project2.getBuffers()[0] waitsFor -> diff --git a/src/atom.coffee b/src/atom.coffee index 7ae64877a..3d6aa7029 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -317,6 +317,10 @@ class Atom else @windowState + # Private: Returns a replicated copy of the current state. + replicate: -> + @windowState.replicate() + crashMainProcess: -> remote.process.crash() diff --git a/src/git.coffee b/src/git.coffee index c9f64eed9..00528af5e 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -71,8 +71,7 @@ class Git @refreshStatus() if project? - @subscribeToBuffer(buffer) for buffer in project.getBuffers() - @subscribe project, 'buffer-created', (buffer) => @subscribeToBuffer(buffer) + @subscribe project.buffers.onEach (buffer) => @subscribeToBuffer(buffer) # Private: Subscribes to buffer events. subscribeToBuffer: (buffer) -> diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 49997859e..4b9c2dd0e 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -34,6 +34,11 @@ class TextBuffer extends Model file: null refcount: 0 + constructor: -> + super + + @loadWhenAttached = @getState()? + # Private: Called by telepath attached: -> @loaded = false @@ -45,6 +50,8 @@ class TextBuffer extends Model @setPath(@filePath) + @load() if @loadWhenAttached + # Private: Called by telepath beforePersistence: -> @modifiedWhenLastPersisted = @isModified() From 28943a35dafe1379bee921668442c591cfdadf68 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:38:10 -0800 Subject: [PATCH 28/49] Use getWindowState instead of referencing window state directly --- src/atom.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom.coffee b/src/atom.coffee index 3d6aa7029..300aea0c2 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -319,7 +319,7 @@ class Atom # Private: Returns a replicated copy of the current state. replicate: -> - @windowState.replicate() + @getWindowState().replicate() crashMainProcess: -> remote.process.crash() From 3ec237824235a469f79ebe68c01597693284e6ca Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:45:59 -0800 Subject: [PATCH 29/49] Access project from atom global --- src/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 4b3fdb8a1..2f8720e67 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -589,7 +589,7 @@ class Editor extends View # Checkout the HEAD revision of this editor's file. checkoutHead: -> if path = @getPath() - @project.getRepo()?.checkoutHead(path) + atom.project.getRepo()?.checkoutHead(path) # {Delegates to: EditSession.setText} setText: (text) -> @activeEditSession.setText(text) From 7d87ae00ff688530e0768707a1337dfea0d2819a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:48:33 -0800 Subject: [PATCH 30/49] Use Atom::replicate for second project --- spec/pane-spec.coffee | 4 ++-- spec/project-spec.coffee | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 0b5e4fe3b..b892995c7 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -699,11 +699,11 @@ describe "Pane", -> it "focuses the pane after attach only if had focus when serialized", -> reloadContainer = -> - projectState = project.serialize() + projectReplica = atom.replicate().get('project') containerState = container.serialize() container.remove() project.destroy() - window.project = deserialize(projectState) + window.project = projectReplica container = deserialize(containerState) pane = container.getRoot() container.attachToDom() diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 5df379830..e205662ed 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -19,7 +19,8 @@ describe "Project", -> it "destroys unretained buffers and does not include them in the serialized state", -> project.bufferForPathSync('a') expect(project.getBuffers().length).toBe 1 - deserializedProject = deserialize(project.serialize()) + atom.getWindowState().serializeForPersistence() + deserializedProject = atom.replicate().get('project') expect(deserializedProject.getBuffers().length).toBe 0 expect(project.getBuffers().length).toBe 0 From 11f1ef9d8bd84b5d2a737ec7d83fb49ba1c62d40 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:55:06 -0800 Subject: [PATCH 31/49] Destroy unretained buffers in beforePersistence --- src/project.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/project.coffee b/src/project.coffee index c76b3f0ca..e4c10fe03 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -38,6 +38,10 @@ class Project extends Model @editSessions = [] @setPath(@path) + # Private: + beforePersistence: -> + @destroyUnretainedBuffers() + # Public: registerOpener: (opener) -> @openers.push(opener) From e4b3d3a83c6653ebc451eb5054957084db2620e3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 12:57:29 -0800 Subject: [PATCH 32/49] Call getValues() when iterating over buffers --- src/project.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index e4c10fe03..13f2bd2f7 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -300,7 +300,7 @@ class Project extends Model replace: (regex, replacementText, filePaths, iterator) -> deferred = Q.defer() - openPaths = (buffer.getPath() for buffer in @buffers) + openPaths = (buffer.getPath() for buffer in @buffers.getValues()) outOfProcessPaths = _.difference(filePaths, openPaths) inProcessFinished = !openPaths.length @@ -318,7 +318,7 @@ class Project extends Model task.on 'replace:path-replaced', iterator - for buffer in @buffers + for buffer in @buffers.getValues() replacements = buffer.replace(regex, replacementText, iterator) iterator({filePath: buffer.getPath(), replacements}) if replacements From 8372adb38ad86d2b17e929b17b4884a17430ad5a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 13:03:00 -0800 Subject: [PATCH 33/49] Remove spec for removed TextBuffer::getRelativePath --- spec/text-buffer-spec.coffee | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index 9bc13b70c..80d52b7a4 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -554,35 +554,6 @@ describe 'TextBuffer', -> waitsFor -> changeHandler.callCount > 0 - describe ".getRelativePath()", -> - [filePath, newPath, bufferToChange, eventHandler] = [] - - beforeEach -> - filePath = path.join(__dirname, "fixtures", "atom-manipulate-me") - newPath = "#{filePath}-i-moved" - fs.writeFileSync(filePath, "") - bufferToChange = project.bufferForPathSync(filePath) - eventHandler = jasmine.createSpy('eventHandler') - bufferToChange.on 'path-changed', eventHandler - - afterEach -> - bufferToChange.destroy() - fs.removeSync(filePath) if fs.existsSync(filePath) - fs.removeSync(newPath) if fs.existsSync(newPath) - - it "updates when the text buffer's file is moved", -> - expect(bufferToChange.getRelativePath()).toBe('atom-manipulate-me') - - jasmine.unspy(window, "setTimeout") - eventHandler.reset() - fs.moveSync(filePath, newPath) - - waitsFor "buffer path change", -> - eventHandler.callCount > 0 - - runs -> - expect(bufferToChange.getRelativePath()).toBe('atom-manipulate-me-i-moved') - describe ".getTextInRange(range)", -> describe "when range is empty", -> it "returns an empty string", -> From d3fed57cb36776fce4fdbb5dc727741b75056d1e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 13:08:06 -0800 Subject: [PATCH 34/49] Only serialize project state for persistence --- spec/project-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index e205662ed..92036fa85 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -19,7 +19,7 @@ describe "Project", -> it "destroys unretained buffers and does not include them in the serialized state", -> project.bufferForPathSync('a') expect(project.getBuffers().length).toBe 1 - atom.getWindowState().serializeForPersistence() + project.getState().serializeForPersistence() deserializedProject = atom.replicate().get('project') expect(deserializedProject.getBuffers().length).toBe 0 expect(project.getBuffers().length).toBe 0 From 93bfe0edf6623a2cda96a831c888d9ff96115862 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 13:14:53 -0800 Subject: [PATCH 35/49] Store path when set in project --- src/project.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/project.coffee b/src/project.coffee index 13f2bd2f7..9565e6181 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -73,6 +73,7 @@ class Project extends Model # Public: Sets the project's fullpath. setPath: (projectPath) -> + @path = projectPath @rootDirectory?.off() @destroyRepo() From f6c8a435aef553847267e30187ae5df05da98cc4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 18:11:15 -0800 Subject: [PATCH 36/49] Upgrade to telepath@0.37.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 100d3a727..15f2e78cc 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.35.0", + "telepath": "0.37.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, From a45dd3fe37dc4a720c460e2b473f0e9b1004a25f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 14 Nov 2013 19:21:05 -0800 Subject: [PATCH 37/49] Register deepest model classes first --- package.json | 2 +- src/atom.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 15f2e78cc..0769dc3f2 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "season": "0.14.0", "semver": "1.1.4", "space-pen": "2.0.0", - "telepath": "0.37.0", + "telepath": "0.38.0", "temp": "0.5.0", "underscore-plus": "0.3.0" }, diff --git a/src/atom.coffee b/src/atom.coffee index 300aea0c2..7bbc2b5ff 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -295,7 +295,7 @@ class Atom doc = Document.deserialize(documentState) if documentState? doc ?= Document.create() - doc.registerModelClasses(require('./project'), require('./text-buffer')) + doc.registerModelClasses(require('./text-buffer'), require('./project')) # TODO: Remove this when everything is using telepath models if @site? @site.setRootDocument(doc) From 19d680544bf7bb976f1e5616b5c93f94fdfa64f2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:07:56 -0800 Subject: [PATCH 38/49] Use Atom::replicate to obtain second project --- spec/root-view-spec.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/root-view-spec.coffee b/spec/root-view-spec.coffee index 65222bd84..1cdec3870 100644 --- a/spec/root-view-spec.coffee +++ b/spec/root-view-spec.coffee @@ -20,10 +20,11 @@ describe "RootView", -> refreshRootViewAndProject = -> rootViewState = rootView.serialize() - projectState = project.serialize() + project.getState().serializeForPersistence() + project2 = atom.replicate().get('project') rootView.remove() project.destroy() - window.project = deserialize(projectState) + window.project = project2 window.rootView = deserialize(rootViewState) rootView.attachToDom() From 12dd4124392ddba07b20e5fd76cec8cc753cb72f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:14:11 -0800 Subject: [PATCH 39/49] Restore relative path as uri of TextBuffer --- src/text-buffer.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 4b9c2dd0e..f01f3bd9d 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -164,7 +164,7 @@ class TextBuffer extends Model @file?.getPath() getUri: -> - @getPath() + atom.project.relativize(@getPath()) # Sets the path for the file. # From 1d4f2fba8bffb49c5507aec432d45df97c7ccd93 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:44:02 -0800 Subject: [PATCH 40/49] Use id provide by telepath.Model --- src/text-buffer.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index f01f3bd9d..a0b864a00 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -1,5 +1,4 @@ {Emitter, Subscriber} = require 'emissary' -guid = require 'guid' Q = require 'q' {P} = require 'scandal' telepath = require 'telepath' @@ -20,7 +19,6 @@ class TextBuffer extends Model @properties text: -> new telepath.String('', replicated: false) - id: -> guid.create().toString() filePath: null relativePath: null modifiedWhenLastPersisted: false From 9067c65a41fd384ffd378cbfbf9bd79ac4270d07 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:44:16 -0800 Subject: [PATCH 41/49] Use Atom::replicate to test serialization --- spec/text-buffer-spec.coffee | 40 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/spec/text-buffer-spec.coffee b/spec/text-buffer-spec.coffee index 80d52b7a4..b818840ee 100644 --- a/spec/text-buffer-spec.coffee +++ b/spec/text-buffer-spec.coffee @@ -13,11 +13,11 @@ describe 'TextBuffer', -> buffer = project.bufferForPathSync(filePath) afterEach -> - buffer?.release() + buffer?.destroy() describe 'constructor', -> beforeEach -> - buffer.release() + buffer.destroy() buffer = null describe "when given a path", -> @@ -897,20 +897,25 @@ describe 'TextBuffer', -> expect(buffer.getText()).toBe "\ninitialtexthello\n1\n2\n" describe "serialization", -> - buffer2 = null + [buffer2, project2] = [] + + beforeEach -> + buffer.destroy() + + filePath = temp.openSync('atom').path + fs.writeFileSync(filePath, "words") + buffer = project.bufferForPathSync(filePath) afterEach -> buffer2?.release() + project2?.destroy() describe "when the serialized buffer had no unsaved changes", -> it "loads the current contents of the file at the serialized path", -> expect(buffer.isModified()).toBeFalsy() - buffer.getState().serializeForPersistence() - state = buffer.getState().clone() - state.get('text').insertTextAtPoint([0, 0], 'simulate divergence of on-disk contents from serialized contents') - - buffer2 = project.addBuffer(new TextBuffer(state)) + project2 = atom.replicate().get('project') + buffer2 = project2.getBuffers()[0] waitsForPromise -> buffer2.load() @@ -923,19 +928,11 @@ describe 'TextBuffer', -> describe "when the serialized buffer had unsaved changes", -> describe "when the disk contents were changed since serialization", -> it "loads the disk contents instead of the previous unsaved state", -> - buffer.release() - - filePath = temp.openSync('atom').path - fs.writeFileSync(filePath, "words") - buffer = project.addBuffer(new TextBuffer({filePath})) buffer.setText("BUFFER CHANGE") - - buffer.getState().serializeForPersistence() - state = buffer.getState().clone() - expect(state.getObject('text')).toBe 'BUFFER CHANGE' fs.writeFileSync(filePath, "DISK CHANGE") - buffer2 = project.addBuffer(new TextBuffer(state)) + project2 = atom.replicate().get('project') + buffer2 = project2.getBuffers()[0] waitsFor -> buffer2.cachedDiskContents @@ -949,12 +946,11 @@ describe 'TextBuffer', -> it "restores the previous unsaved state of the buffer", -> previousText = buffer.getText() buffer.setText("abc") + buffer.retain() buffer.getState().serializeForPersistence() - state = buffer.getState().clone() - expect(state.getObject('text')).toBe 'abc' - - buffer2 = project.addBuffer(new TextBuffer(state)) + project2 = atom.replicate().get('project') + buffer2 = project2.getBuffers()[0] waitsForPromise -> buffer2.load() From 1c8df2c0b540e9bea7083199c0ce8f6928fbe560 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:48:36 -0800 Subject: [PATCH 42/49] :lipstick: Organize imports in TextBuffer --- src/text-buffer.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index a0b864a00..12a968ef1 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -1,19 +1,19 @@ +_ = require 'underscore-plus' {Emitter, Subscriber} = require 'emissary' Q = require 'q' {P} = require 'scandal' telepath = require 'telepath' -_ = require 'underscore-plus' File = require './file' -{Point, Range, Model} = telepath +{Point, Range} = telepath # Private: Represents the contents of a file. # # The `Buffer` is often associated with a {File}. However, this is not always # the case, as a `Buffer` could be an unsaved chunk of text. module.exports = -class TextBuffer extends Model +class TextBuffer extends telepath.Model Emitter.includeInto(this) Subscriber.includeInto(this) From e2d4b58d5f48fff603354acf038dd35dd6797433 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:49:15 -0800 Subject: [PATCH 43/49] Remove unused Range --- src/project.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index 9565e6181..03e843f74 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -5,7 +5,6 @@ _ = require 'underscore-plus' fs = require 'fs-plus' Q = require 'q' telepath = require 'telepath' -{Model, Range} = telepath TextBuffer = require './text-buffer' EditSession = require './edit-session' @@ -19,7 +18,7 @@ Git = require './git' # Ultimately, a project is a git directory that's been opened. It's a collection # of directories and files that you can operate on. module.exports = -class Project extends Model +class Project extends telepath.Model Emitter.includeInto(this) @properties From 1d7b4c5f9aed44208b12cc1f22965ad8482a83bf Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:49:54 -0800 Subject: [PATCH 44/49] Updating places still using Buffer instead of TextBuffer --- src/text-buffer.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 12a968ef1..fd754d6a6 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -10,8 +10,8 @@ File = require './file' # Private: Represents the contents of a file. # -# The `Buffer` is often associated with a {File}. However, this is not always -# the case, as a `Buffer` could be an unsaved chunk of text. +# The `TextBuffer` is often associated with a {File}. However, this is not always +# the case, as a `TextBuffer` could be an unsaved chunk of text. module.exports = class TextBuffer extends telepath.Model Emitter.includeInto(this) @@ -672,7 +672,7 @@ class TextBuffer extends telepath.Model console.log row, line, line.length getDebugSnapshot: -> - lines = ['Buffer:'] + lines = ['TextBuffer:'] for row in [0..@getLastRow()] lines.push "#{row}: #{@lineForRow(row)}" lines.join('\n') From 0b12f01206e945b2c4e3b119862d67bf081d45d8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 10:59:49 -0800 Subject: [PATCH 45/49] Use Project::bufferForPathSync instead of buildBufferSync --- spec/selection-spec.coffee | 2 +- spec/tokenized-buffer-spec.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index da23d73e1..e5aa2c055 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -4,7 +4,7 @@ describe "Selection", -> [buffer, editSession, selection] = [] beforeEach -> - buffer = project.buildBufferSync('sample.js') + buffer = project.bufferForPathSync('sample.js') editSession = new EditSession(buffer: buffer, tabLength: 2) selection = editSession.getSelection() diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index f24cfae6e..488c9cc22 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -350,7 +350,7 @@ describe "TokenizedBuffer", -> describe "when the buffer contains surrogate pairs", -> beforeEach -> atom.activatePackage('language-javascript', sync: true) - buffer = project.buildBufferSync 'sample-with-pairs.js' + buffer = project.bufferForPathSync 'sample-with-pairs.js' buffer.setText """ 'abc\uD835\uDF97def' //\uD835\uDF97xyz From b137f1a3e3cdb2c4c9809edd86f1367ed82a0c8c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 11:03:48 -0800 Subject: [PATCH 46/49] Upgrade to emissary@0.17.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0769dc3f2..b3942fee1 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "clear-cut": "0.1.0", "coffee-script": "1.6.3", "coffeestack": "0.6.0", - "emissary": "0.15.0", + "emissary": "0.17.0", "first-mate": "0.5.0", "fs-plus": "0.9.0", "fuzzaldrin": "0.1.0", From 20811a9f52317c8fef159f0b00b650d6a60fea48 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 11:05:42 -0800 Subject: [PATCH 47/49] :memo: Mention which methods are telepath hooks --- src/project.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index 03e843f74..248f382a6 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -31,13 +31,13 @@ class Project extends telepath.Model repoName = repoName.replace(/\.git$/, '') path.join(atom.config.get('core.projectHome'), repoName) - # Private: + # Private: Called by telepath. attached: -> @openers = [] @editSessions = [] @setPath(@path) - # Private: + # Private: Called by telepath. beforePersistence: -> @destroyUnretainedBuffers() From 3fe88c4df1b0881ca5313f404b4d14e9794608c5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 11:07:06 -0800 Subject: [PATCH 48/49] :lipstick: Add period to comment --- src/text-buffer.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index fd754d6a6..60895df9d 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -37,7 +37,7 @@ class TextBuffer extends telepath.Model @loadWhenAttached = @getState()? - # Private: Called by telepath + # Private: Called by telepath. attached: -> @loaded = false @useSerializedText = @modifiedWhenLastPersisted != false @@ -50,7 +50,7 @@ class TextBuffer extends telepath.Model @load() if @loadWhenAttached - # Private: Called by telepath + # Private: Called by telepath. beforePersistence: -> @modifiedWhenLastPersisted = @isModified() @digestWhenLastPersisted = @file?.getDigest() From de4d3dbbe9e9a2e02c43bbe21cac868c52b9f564 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 15 Nov 2013 11:34:16 -0800 Subject: [PATCH 49/49] Create new project when state doesn't return a Project --- src/atom.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 7bbc2b5ff..f9f9e119b 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -120,11 +120,10 @@ class Atom deserializeProject: -> Project = require './project' - state = @getWindowState() - @project = state.get('project') - unless @project? + @project = @getWindowState('project') + unless @project instanceof Project @project = new Project(path: @getLoadSettings().initialPath) - state.set('project', @project) + @setWindowState('project', @project) deserializeRootView: -> RootView = require './root-view'