mirror of
https://github.com/atom/atom.git
synced 2026-02-05 20:25:04 -05:00
115 lines
3.1 KiB
CoffeeScript
115 lines
3.1 KiB
CoffeeScript
EventEmitter = require 'event-emitter'
|
|
|
|
fs = require 'fs'
|
|
fsUtils = require 'fs-utils'
|
|
pathWatcher = require 'pathwatcher'
|
|
_ = require 'underscore'
|
|
|
|
# Public: Represents an individual file in the editor.
|
|
#
|
|
# The entry point for this class is in two locations:
|
|
# * {Buffer}, which associates text contents with a file
|
|
# * {Directory}, which associcates the children of a directory as files
|
|
module.exports =
|
|
class File
|
|
path: null
|
|
cachedContents: null
|
|
|
|
# Public: Creates a new file.
|
|
#
|
|
# path - A {String} representing the file path
|
|
# symlink - A {Boolean} indicating if the path is a symlink (default: false)
|
|
constructor: (@path, @symlink=false) ->
|
|
try
|
|
if fs.statSync(@path).isDirectory()
|
|
throw new Error("#{@path} is a directory")
|
|
|
|
# Public: Sets the path for the file.
|
|
#
|
|
# path - A {String} representing the new file path
|
|
setPath: (@path) ->
|
|
|
|
# Public: Retrieves the path for the file.
|
|
#
|
|
# Returns a {String}.
|
|
getPath: -> @path
|
|
|
|
# Public: Gets the file's basename--that is, the file without any directory information.
|
|
#
|
|
# Returns a {String}.
|
|
getBaseName: ->
|
|
fsUtils.base(@path)
|
|
|
|
# Public: Writes (and saves) new contents to the file.
|
|
#
|
|
# text - A {String} representing the new contents.
|
|
write: (text) ->
|
|
previouslyExisted = @exists()
|
|
@cachedContents = text
|
|
fsUtils.write(@getPath(), text)
|
|
@subscribeToNativeChangeEvents() if not previouslyExisted and @subscriptionCount() > 0
|
|
|
|
# Public: Reads the file.
|
|
#
|
|
# flushCache - A {Boolean} indicating if the cache should be erased--_i.e._, a force read is performed
|
|
#
|
|
# Returns a {String}.
|
|
read: (flushCache)->
|
|
if not @exists()
|
|
@cachedContents = null
|
|
else if not @cachedContents? or flushCache
|
|
@cachedContents = fsUtils.read(@getPath())
|
|
else
|
|
@cachedContents
|
|
|
|
# Public: Checks to see if a file exists.
|
|
#
|
|
# Returns a {Boolean}.
|
|
exists: ->
|
|
fsUtils.exists(@getPath())
|
|
|
|
###
|
|
# Internal #
|
|
###
|
|
|
|
afterSubscribe: ->
|
|
@subscribeToNativeChangeEvents() if @exists() and @subscriptionCount() == 1
|
|
|
|
afterUnsubscribe: ->
|
|
@unsubscribeFromNativeChangeEvents() if @subscriptionCount() == 0
|
|
|
|
handleNativeChangeEvent: (eventType, path) ->
|
|
if eventType is "delete"
|
|
@unsubscribeFromNativeChangeEvents()
|
|
@detectResurrectionAfterDelay()
|
|
else if eventType is "rename"
|
|
@setPath(path)
|
|
@trigger "moved"
|
|
else if eventType is "change"
|
|
oldContents = @read()
|
|
newContents = @read(true)
|
|
return if oldContents == newContents
|
|
@trigger 'contents-changed'
|
|
|
|
detectResurrectionAfterDelay: ->
|
|
_.delay (=> @detectResurrection()), 50
|
|
|
|
detectResurrection: ->
|
|
if @exists()
|
|
@subscribeToNativeChangeEvents()
|
|
@handleNativeChangeEvent("change", @getPath())
|
|
else
|
|
@cachedContents = null
|
|
@trigger "removed"
|
|
|
|
subscribeToNativeChangeEvents: ->
|
|
@watchSubscription = pathWatcher.watch @path, (eventType, path) =>
|
|
@handleNativeChangeEvent(eventType, path)
|
|
|
|
unsubscribeFromNativeChangeEvents: ->
|
|
if @watchSubscription
|
|
@watchSubscription.close()
|
|
@watchSubscription = null
|
|
|
|
_.extend File.prototype, EventEmitter
|