diff --git a/package.json b/package.json index 9edc28134..664f530d2 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "pegjs": "0.8.0", "property-accessors": "1.x", "q": "1.0.x", + "runas": "0.4.0", "scandal": "0.14.0", "season": "1.x", "semver": "1.1.4", diff --git a/src/file.coffee b/src/file.coffee index beedf73f8..b4fffe060 100644 --- a/src/file.coffee +++ b/src/file.coffee @@ -5,6 +5,7 @@ Q = require 'q' {Emitter} = require 'emissary' _ = require 'underscore-plus' fs = require 'fs-plus' +runas = require 'runas' # Public: Represents an individual file. # @@ -60,8 +61,8 @@ class File # Public: Overwrites the file with the given String. write: (text) -> previouslyExisted = @exists() + @writeFileWithPrivilegeEscalationSync(@getPath(), text) @cachedContents = text - fs.writeFileSync(@getPath(), text) @subscribeToNativeChangeEvents() if not previouslyExisted and @hasSubscriptions() # Deprecated @@ -122,6 +123,21 @@ class File getDigest: -> @digest ? @setDigest(@readSync()) + # Writes the text to specified path. + # + # Privilege escalation would be asked when current user doesn't have + # permission to the path. + writeFileWithPrivilegeEscalationSync: (path, text) -> + try + fs.writeFileSync(path, text) + catch error + if error.code is 'EACCES' and process.platform is 'darwin' + authopen = '/usr/libexec/authopen' # man 1 authopen + unless runas(authopen, ['-w', '-c', path], stdin: text) is 0 + throw error + else + throw error + handleNativeChangeEvent: (eventType, path) -> if eventType is "delete" @unsubscribeFromNativeChangeEvents() diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 2adc613c0..c884e7e0e 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -194,8 +194,8 @@ class TextBuffer extends TextBufferCore @emit 'will-be-saved', this @setPath(filePath) - @cachedDiskContents = @getText() @file.write(@getText()) + @cachedDiskContents = @getText() @conflict = false @emitModifiedStatusChanged(false) @emit 'saved', this