Comparar commits

..

27 Commits

Autor SHA1 Mensagem Data
Kevin Sawicki 9105348c8c Merge pull request #5424 from atom/ks-handle-save-errors-in-pane
Show custom notifications for more save errors
2015-02-05 16:22:26 -08:00
Kevin Sawicki 30419027a8 Show notification on config save failures 2015-02-05 15:34:17 -08:00
Kevin Sawicki 5de95759cd Spy on editor.save 2015-02-05 15:24:00 -08:00
Kevin Sawicki f7502d8508 Handle UNKNOWN save errors 2015-02-05 15:17:23 -08:00
Kevin Sawicki c9f13afb72 Remove stray logging 2015-02-05 15:12:20 -08:00
Kevin Sawicki e51c8f3407 Add specs for save/saveAs error handling 2015-02-05 15:07:42 -08:00
Kevin Sawicki 63ee46023d Remove profiling 2015-02-05 14:57:09 -08:00
Kevin Sawicki 68e5839b14 Add missing error var 2015-02-05 14:44:16 -08:00
Kevin Sawicki 477801ba52 Remove save error reporting from Workspace 2015-02-05 14:43:50 -08:00
Kevin Sawicki 3850550345 Handle save errors in Pane 2015-02-05 14:42:21 -08:00
Kevin Sawicki 728a8049d9 ⬆️ markdown-preview@0.134 2015-02-05 13:42:55 -08:00
Kevin Sawicki 77741b6f3f Set ATOM_HOME as early as possible in render process
Moves it from window-bootstrap.coffee to index.js so it runs before
the coffee cache is registered.

Refs #5412
2015-02-05 12:18:51 -08:00
Kevin Sawicki 4597dd5594 Add render process check for ATOM_HOME
Setting it in the browser process does not seem to make it into
the render processes on Linux.

Closes #5412
2015-02-05 12:11:13 -08:00
Kevin Sawicki 04d015a7e0 Use app.getHomeDir 2015-02-05 11:39:58 -08:00
Kevin Sawicki 4bd07be7d8 ⬆️ timecop@0.29 2015-02-05 10:55:06 -08:00
Kevin Sawicki 40de6a7114 Add executable value to desktop file template
Closes #5419
2015-02-05 10:12:30 -08:00
Kevin Sawicki 9100d20dc4 Merge pull request #5417 from atom/iz-fix-semver
Fix atom engine semver in upgrading docs
2015-02-05 08:55:35 -08:00
Ivan Žužak 4361b67214 Fix atom engine semver in upgrading docs 2015-02-05 15:07:16 +01:00
Kevin Sawicki 83c8d904cf 🎨 Add space before arrow 2015-02-04 17:44:33 -08:00
Kevin Sawicki 3257d17fc0 Merge pull request #5408 from atom/add-csharp
Add language-csharp to core packages
2015-02-04 17:28:19 -08:00
Kevin Sawicki fd1d872840 Prompt split editors to save on close
Previously an editor that was split into multiple panes would not
prompt to save correctly when the window was unloading.

This adds a new `windowCloseRequested` option passed through from the
beforeunload handler to the editor so that it can specially handle this
case.

Closes #5257
2015-02-04 17:14:46 -08:00
Kevin Sawicki c5b6b90c88 Normalize opened paths to handle ~
Closes #3829
2015-02-04 16:39:25 -08:00
Kevin Sawicki 9618ec45cf Remove unused require 2015-02-04 15:35:41 -08:00
Kevin Sawicki 6e3d41f433 Suppress deprecations in BufferedNodeProcess
This keeps it consistent with the render process which also suppresses
deprecations

Closes #5383
2015-02-04 15:27:17 -08:00
Kevin Sawicki 6f438ca7da ⬆️ language-csharp@0.5 2015-02-04 14:44:49 -08:00
Daniel Hengeveld c629eb73b2 Add language-csharp to core packages 2015-02-04 14:16:01 -08:00
Kevin Sawicki cbe5eff04c Tweak chocolatey instructions
chocolatey now uses the new installer
2015-02-04 13:35:47 -08:00
27 arquivos alterados com 223 adições e 243 exclusões
+2 -12
Ver Arquivo
@@ -24,18 +24,8 @@ Atom will automatically update when a new release is available.
You can also download an `atom-windows.zip` file from the [releases page](https://github.com/atom/atom/releases/latest).
The `.zip` version will not automatically update.
#### Uninstalling Chocolatey Version
The recommended installation of Atom on Windows used to be using [Chocolatey](https://chocolatey.org/packages/Atom/).
This is no longer recommended now that the Atom Windows installer & auto-updater
exists.
To switch from Chocolatey to the new installer:
* Upgrade to Atom 0.155 or above by running `cup Atom`
* Run `cuninst Atom` to uninstall the Chocolatey version of Atom
* This will not delete any of your installed packages or Atom config files.
* Download the latest [AtomSetup.exe installer](https://github.com/atom/atom/releases/latest).
* Double-click the downloaded file to install Atom
Using [chocolatey](https://chocolatey.org/)? Run `cinst Atom` to install
the latest version of Atom.
### Debian Linux (Ubuntu)
+2 -2
Ver Arquivo
@@ -222,7 +222,7 @@ module.exports = (grunt) ->
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
ciTasks = ['output-disk-space', 'download-atom-shell', 'download-atom-shell-chromedriver', 'build']
ciTasks = ['output-disk-space', 'download-atom-shell', 'build']
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
ciTasks.push('set-version', 'check-licenses', 'lint')
ciTasks.push('mkdeb') if process.platform is 'linux'
@@ -232,6 +232,6 @@ module.exports = (grunt) ->
ciTasks.push('publish-build')
grunt.registerTask('ci', ciTasks)
defaultTasks = ['download-atom-shell', 'download-atom-shell-chromedriver', 'build', 'set-version']
defaultTasks = ['download-atom-shell', 'build', 'set-version']
defaultTasks.push 'install' unless process.platform is 'linux'
grunt.registerTask('default', defaultTasks)
+1 -2
Ver Arquivo
@@ -19,7 +19,7 @@
"grunt-contrib-csslint": "~0.1.2",
"grunt-contrib-less": "~0.8.0",
"grunt-cson": "0.14.0",
"grunt-download-atom-shell": "~0.12.0",
"grunt-download-atom-shell": "~0.11.0",
"grunt-lesslint": "0.13.0",
"grunt-peg": "~1.1.0",
"grunt-shell": "~0.3.1",
@@ -31,7 +31,6 @@
"request": "~2.27.0",
"rimraf": "~2.2.2",
"runas": "~1.0.1",
"selenium-webdriver": "^2.44.0",
"tello": "1.0.4",
"temp": "~0.8.1",
"underscore-plus": "1.x",
+2 -2
Ver Arquivo
@@ -47,9 +47,9 @@ module.exports = (grunt) ->
{description} = grunt.file.readJSON('package.json')
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'atom.png')
installDir = path.join(installDir, '.') # To prevent "Exec=/usr/local//share/atom/atom"
executable = path.join(shareDir, 'atom')
template = _.template(String(fs.readFileSync(desktopFile)))
filled = template({description, installDir, iconName})
filled = template({description, iconName, executable})
grunt.file.write(desktopInstallFile, filled)
-12
Ver Arquivo
@@ -85,27 +85,15 @@ module.exports = (grunt) ->
appPath = getAppPath()
resourcePath = process.cwd()
coreSpecsPath = path.resolve('spec')
chromedriverPath = path.join(resourcePath, "atom-shell", "chromedriver")
if process.platform in ['darwin', 'linux']
options =
cmd: appPath
args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}"]
opts:
env: _.extend({}, process.env,
ATOM_INTEGRATION_TESTS_ENABLED: true
PATH: [process.env.path, chromedriverPath].join(":")
)
else if process.platform is 'win32'
options =
cmd: process.env.comspec
args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}", "--log-file=ci.log"]
opts:
env: _.extend({}, process.env,
ATOM_INTEGRATION_TESTS_ENABLED: true
PATH: [process.env.path, chromedriverPath].join(";")
)
spawn options, (error, results, code) ->
if process.platform is 'win32'
+1 -1
Ver Arquivo
@@ -63,7 +63,7 @@ When you are deprecation free and all done converting, upgrade the `engines` fie
```json
{
"engines": {
"atom": ">=0.174.0, <2.0.0"
"atom": ">=0.174.0 <2.0.0"
}
}
```
+4 -3
Ver Arquivo
@@ -31,7 +31,7 @@
"emissary": "^1.3.1",
"event-kit": "^1.0.2",
"first-mate": "^3.0.0",
"fs-plus": "^2.3.2",
"fs-plus": "^2.5",
"fstream": "0.1.24",
"fuzzaldrin": "^2.1",
"git-utils": "^3.0.0",
@@ -103,7 +103,7 @@
"incompatible-packages": "0.21.0",
"keybinding-resolver": "0.27.0",
"link": "0.30.0",
"markdown-preview": "0.133.0",
"markdown-preview": "0.134.0",
"metrics": "0.42.0",
"notifications": "0.26.0",
"open-on-github": "0.32.0",
@@ -116,7 +116,7 @@
"styleguide": "0.43.0",
"symbols-view": "0.81.0",
"tabs": "0.64.0",
"timecop": "0.28.0",
"timecop": "0.29.0",
"tree-view": "0.154.0",
"update-package-dependencies": "0.8.0",
"welcome": "0.21.0",
@@ -125,6 +125,7 @@
"language-c": "0.38.0",
"language-clojure": "0.10.0",
"language-coffee-script": "0.39.0",
"language-csharp": "0.5.0",
"language-css": "0.27.0",
"language-gfm": "0.63.0",
"language-git": "0.10.0",
+39
Ver Arquivo
@@ -0,0 +1,39 @@
path = require 'path'
BufferedNodeProcess = require '../src/buffered-node-process'
describe "BufferedNodeProcess", ->
it "executes the script in a new process", ->
exit = jasmine.createSpy('exitCallback')
output = ''
stdout = (lines) -> output += lines
error = ''
stderr = (lines) -> error += lines
args = ['hi']
command = path.join(__dirname, 'fixtures', 'script.js')
new BufferedNodeProcess({command, args, stdout, stderr, exit})
waitsFor ->
exit.callCount is 1
runs ->
expect(output).toBe 'hi'
expect(error).toBe ''
expect(args).toEqual ['hi']
it "suppresses deprecations in the new process", ->
exit = jasmine.createSpy('exitCallback')
output = ''
stdout = (lines) -> output += lines
error = ''
stderr = (lines) -> error += lines
command = path.join(__dirname, 'fixtures', 'script-with-deprecations.js')
new BufferedNodeProcess({command, stdout, stderr, exit})
waitsFor ->
exit.callCount is 1
runs ->
expect(output).toBe 'hi'
expect(error).toBe ''
+17
Ver Arquivo
@@ -666,6 +666,23 @@ describe "Config", ->
foo:
bar: 'coffee'
describe "when an error is thrown writing the file to disk", ->
addErrorHandler = null
beforeEach ->
atom.notifications.onDidAddNotification addErrorHandler = jasmine.createSpy()
it "creates a notification", ->
jasmine.unspy CSON, 'writeFileSync'
spyOn(CSON, 'writeFileSync').andCallFake ->
error = new Error()
error.code = 'EPERM'
error.path = atom.config.getUserConfigPath()
throw error
save = -> atom.config.save()
expect(save).not.toThrow()
expect(addErrorHandler.callCount).toBe 1
describe ".loadUserConfig()", ->
beforeEach ->
expect(fs.existsSync(atom.config.configDirPath)).toBeFalsy()
+2
Ver Arquivo
@@ -0,0 +1,2 @@
require('fs').existsSync('hi');
process.stdout.write('hi');
+1
Ver Arquivo
@@ -0,0 +1 @@
process.stdout.write(process.argv[2]);
-36
Ver Arquivo
@@ -1,36 +0,0 @@
#!/bin/bash
# This script wraps the `Atom` binary, allowing the `chromedriver` server to
# execute it with positional arguments. `chromedriver` only allows 'switches'
# to be specified when starting a browser, not positional arguments, so this
# script accepts two special switches:
#
# * `atom-path` The path to the `Atom` binary
# * `atom-args` A space-separated list of positional arguments to pass to Atom.
#
# Any other switches will be passed through to `Atom`.
atom_path=""
atom_switches=()
atom_args=()
for arg in "$@"; do
case $arg in
--atom-path=*)
atom_path="${arg#*=}"
;;
--atom-args=*)
atom_args_string="${arg#*=}"
for atom_arg in $atom_args_string; do
atom_args+=($atom_arg)
done
;;
*)
atom_switches+=($arg)
;;
esac
done
exec $atom_path "${atom_switches[@]}" "${atom_args[@]}"
-107
Ver Arquivo
@@ -1,107 +0,0 @@
# These tests are excluded by default. To run them from the command line:
#
# ATOM_INTEGRATION_TESTS_ENABLED=true apm test
return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED
os = require "os"
fs = require "fs"
path = require "path"
remote = require "remote"
temp = require("temp").track()
{spawn, spawnSync} = require "child_process"
{Builder, By} = require "../../build/node_modules/selenium-webdriver"
AtomPath = remote.process.argv[0]
AtomLauncherPath = path.join(__dirname, "helpers", "atom-launcher.sh")
SocketPath = path.join(os.tmpdir(), "atom-integration-test.sock")
ChromeDriverPort = 9515
describe "Starting Atom", ->
[chromeDriver, driver, tempDirPath] = []
beforeEach ->
tempDirPath = temp.mkdirSync("empty-dir")
waitsFor "chromedriver to start", (done) ->
chromeDriver = spawn "chromedriver", ["--verbose", "--port=#{ChromeDriverPort}"]
chromeDriver.on "error", (error) ->
throw new Error("chromedriver failed to start: #{error.message}")
chromeDriver.stdout.on "data", -> done()
afterEach ->
waitsForPromise -> driver.quit().thenFinally(-> chromeDriver.kill())
startAtom = (args...) ->
driver = new Builder()
.usingServer("http://localhost:#{ChromeDriverPort}")
.withCapabilities(
chromeOptions:
binary: AtomLauncherPath
args: [
"atom-path=#{AtomPath}"
"atom-args=#{args.join(" ")}"
"dev"
"safe"
"user-data-dir=#{temp.mkdirSync('integration-spec-')}"
"socket-path=#{SocketPath}"
]
)
.forBrowser('atom')
.build()
waitsForPromise ->
driver.wait ->
driver.getTitle().then (title) -> title.indexOf("Atom") >= 0
startAnotherAtom = (args...) ->
spawnSync(AtomPath, args.concat([
"--dev",
"--safe",
"--socket-path=#{SocketPath}"
]))
describe "when given the name of a file that doesn't exist", ->
tempFilePath = null
beforeEach ->
tempFilePath = path.join(tempDirPath, "an-existing-file")
fs.writeFileSync(tempFilePath, "This was already here.")
startAtom(path.join(tempDirPath, "new-file"))
it "opens a new window with an empty text editor", ->
waitsForPromise ->
driver.getAllWindowHandles().then (handles) ->
expect(handles.length).toBe 1
driver.executeScript(-> atom.workspace.getActivePane().getItems().length).then (length) ->
expect(length).toBe 1
driver.executeScript(-> atom.workspace.getActiveTextEditor().getText()).then (text) ->
expect(text).toBe("")
driver.findElement(By.tagName("atom-text-editor")).sendKeys("Hello world!")
driver.executeScript(-> atom.workspace.getActiveTextEditor().getText()).then (text) ->
expect(text).toBe "Hello world!"
# Opening another existing file in the same directory reuses the window,
# and opens a new tab for the file.
waitsForPromise ->
startAnotherAtom(tempFilePath)
driver.wait ->
driver.executeScript(-> atom.workspace.getActivePane().getItems().length).then (length) ->
length is 2
driver.executeScript(-> atom.workspace.getActiveTextEditor().getText()).then (text) ->
expect(text).toBe "This was already here."
# Opening a different directory creates a new window.
waitsForPromise ->
startAnotherAtom(temp.mkdirSync("another-empty-dir"))
driver.wait ->
driver.getAllWindowHandles().then (handles) ->
handles.length is 2
describe "when given the name of a directory that exists", ->
beforeEach ->
startAtom(tempDirPath)
it "opens a new window no text editors open", ->
waitsForPromise ->
driver.executeScript(-> atom.workspace.getActiveTextEditor()).then (editor) ->
expect(editor).toBeNull()
+38
Ver Arquivo
@@ -383,6 +383,25 @@ describe "Pane", ->
pane.saveActiveItem()
expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
describe "when the item's saveAs method throws a well-known IO error", ->
notificationSpy = null
beforeEach ->
atom.notifications.onDidAddNotification notificationSpy = jasmine.createSpy()
it "creates a notification", ->
pane.getActiveItem().saveAs = ->
error = new Error("EACCES, permission denied '/foo'")
error.path = '/foo'
error.code = 'EACCES'
throw error
pane.saveActiveItem()
expect(notificationSpy).toHaveBeenCalled()
notification = notificationSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'warning'
expect(notification.getMessage()).toContain 'Permission denied'
expect(notification.getMessage()).toContain '/foo'
describe "::saveActiveItemAs()", ->
pane = null
@@ -404,6 +423,25 @@ describe "Pane", ->
pane.saveActiveItemAs()
expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
describe "when the item's saveAs method throws a well-known IO error", ->
notificationSpy = null
beforeEach ->
atom.notifications.onDidAddNotification notificationSpy = jasmine.createSpy()
it "creates a notification", ->
pane.getActiveItem().saveAs = ->
error = new Error("EACCES, permission denied '/foo'")
error.path = '/foo'
error.code = 'EACCES'
throw error
pane.saveActiveItemAs()
expect(notificationSpy).toHaveBeenCalled()
notification = notificationSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'warning'
expect(notification.getMessage()).toContain 'Permission denied'
expect(notification.getMessage()).toContain '/foo'
describe "::itemForURI(uri)", ->
it "returns the item for which a call to .getURI() returns the given uri", ->
pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])
+2 -2
Ver Arquivo
@@ -305,13 +305,13 @@ window.waitsForPromise = (args...) ->
window.waitsFor timeout, (moveOn) ->
promise = fn()
if shouldReject
(promise.catch ? promise.thenCatch).call(promise, moveOn)
promise.catch(moveOn)
promise.then ->
jasmine.getEnv().currentSpec.fail("Expected promise to be rejected, but it was resolved")
moveOn()
else
promise.then(moveOn)
(promise.catch ? promise.thenCatch).call promise, (error) ->
promise.catch (error) ->
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with #{jasmine.pp(error)}")
moveOn()
+22 -1
Ver Arquivo
@@ -1,5 +1,7 @@
{$, $$} = require '../src/space-pen-extensions'
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
TextEditor = require '../src/text-editor'
WindowEventHandler = require '../src/window-event-handler'
@@ -54,7 +56,7 @@ describe "Window", ->
jasmine.unspy(TextEditor.prototype, "shouldPromptToSave")
beforeUnloadEvent = $.Event(new Event('beforeunload'))
describe "when pane items are are modified", ->
describe "when pane items are modified", ->
it "prompts user to save and calls atom.workspace.confirmClose", ->
editor = null
spyOn(atom.workspace, 'confirmClose').andCallThrough()
@@ -92,6 +94,25 @@ describe "Window", ->
$(window).trigger(beforeUnloadEvent)
expect(atom.confirm).toHaveBeenCalled()
describe "when the same path is modified in multiple panes", ->
it "prompts to save the item", ->
editor = null
filePath = path.join(temp.mkdirSync('atom-file'), 'file.txt')
fs.writeFileSync(filePath, 'hello')
spyOn(atom.workspace, 'confirmClose').andCallThrough()
spyOn(atom, 'confirm').andReturn(0)
waitsForPromise ->
atom.workspace.open(filePath).then (o) -> editor = o
runs ->
atom.workspace.getActivePane().splitRight(copyActiveItem: true)
editor.setText('world')
$(window).trigger(beforeUnloadEvent)
expect(atom.workspace.confirmClose).toHaveBeenCalled()
expect(atom.confirm.callCount).toBe 1
expect(fs.readFileSync(filePath, 'utf8')).toBe 'world'
describe ".unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", ->
workspaceState = atom.workspace.serialize()
+12 -7
Ver Arquivo
@@ -955,9 +955,14 @@ describe "Workspace", ->
expect(editor.isModified()).toBeTruthy()
describe "::saveActivePaneItem()", ->
editor = null
beforeEach ->
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor = o
describe "when there is an error", ->
it "emits a warning notification when the file cannot be saved", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
throw new Error("'/some/file' is a directory")
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
@@ -966,7 +971,7 @@ describe "Workspace", ->
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
it "emits a warning notification when the directory cannot be written to", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
throw new Error("ENOTDIR, not a directory '/Some/dir/and-a-file.js'")
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
@@ -975,7 +980,7 @@ describe "Workspace", ->
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
it "emits a warning notification when the user does not have permission", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
error = new Error("EACCES, permission denied '/Some/dir/and-a-file.js'")
error.code = 'EACCES'
error.path = '/Some/dir/and-a-file.js'
@@ -987,14 +992,14 @@ describe "Workspace", ->
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
it "emits a warning notification when the operation is not permitted", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
error = new Error("EPERM, operation not permitted '/Some/dir/and-a-file.js'")
error.code = 'EPERM'
error.path = '/Some/dir/and-a-file.js'
throw error
it "emits a warning notification when the file is already open by another app", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
error = new Error("EBUSY, resource busy or locked '/Some/dir/and-a-file.js'")
error.code = 'EBUSY'
error.path = '/Some/dir/and-a-file.js'
@@ -1009,7 +1014,7 @@ describe "Workspace", ->
expect(notificaiton.getMessage()).toContain 'Unable to save'
it "emits a warning notification when the file system is read-only", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
error = new Error("EROFS, read-only file system '/Some/dir/and-a-file.js'")
error.code = 'EROFS'
error.path = '/Some/dir/and-a-file.js'
@@ -1024,7 +1029,7 @@ describe "Workspace", ->
expect(notification.getMessage()).toContain 'Unable to save'
it "emits a warning notification when the file cannot be saved", ->
spyOn(Pane::, 'saveActiveItem').andCallFake ->
spyOn(editor, 'save').andCallFake ->
throw new Error("no one knows")
save = -> atom.workspace.saveActivePaneItem()
+9 -12
Ver Arquivo
@@ -5,7 +5,7 @@ AutoUpdateManager = require './auto-update-manager'
BrowserWindow = require 'browser-window'
Menu = require 'menu'
app = require 'app'
fs = require 'fs'
fs = require 'fs-plus'
ipc = require 'ipc'
path = require 'path'
os = require 'os'
@@ -14,7 +14,7 @@ url = require 'url'
{EventEmitter} = require 'events'
_ = require 'underscore-plus'
DefaultSocketPath =
socketPath =
if process.platform is 'win32'
'\\\\.\\pipe\\atom-sock'
else
@@ -31,20 +31,17 @@ class AtomApplication
# Public: The entry point into the Atom application.
@open: (options) ->
options.socketPath ?= DefaultSocketPath
createAtomApplication = -> new AtomApplication(options)
# FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely
# take a few seconds to trigger 'error' event, it could be a bug of node
# or atom-shell, before it's fixed we check the existence of socketPath to
# speedup startup.
if (process.platform isnt 'win32' and not fs.existsSync options.socketPath) or options.test
if (process.platform isnt 'win32' and not fs.existsSync socketPath) or options.test
createAtomApplication()
return
client = net.connect {path: options.socketPath}, ->
client = net.connect {path: socketPath}, ->
client.write JSON.stringify(options), ->
client.end()
app.terminate()
@@ -60,7 +57,7 @@ class AtomApplication
exit: (status) -> app.exit(status)
constructor: (options) ->
{@resourcePath, @version, @devMode, @safeMode, @socketPath} = options
{@resourcePath, @version, @devMode, @safeMode} = options
# Normalize to make sure drive letter case is consistent on Windows
@resourcePath = path.normalize(@resourcePath) if @resourcePath
@@ -122,15 +119,15 @@ class AtomApplication
connection.on 'data', (data) =>
@openWithOptions(JSON.parse(data))
server.listen @socketPath
server.listen socketPath
server.on 'error', (error) -> console.error 'Application server failed', error
deleteSocketFile: ->
return if process.platform is 'win32'
if fs.existsSync(@socketPath)
if fs.existsSync(socketPath)
try
fs.unlinkSync(@socketPath)
fs.unlinkSync(socketPath)
catch error
# Ignore ENOENT errors in case the file was deleted between the exists
# check and the call to unlink sync. This occurred occasionally on CI
@@ -345,6 +342,7 @@ class AtomApplication
# :window - {AtomWindow} to open file paths in.
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, window}={}) ->
{pathToOpen, initialLine, initialColumn} = @locationForPathToOpen(pathToOpen)
pathToOpen = fs.normalize(pathToOpen)
unless pidToKillWhenClosed or newWindow
pathToOpenStat = fs.statSyncNoException(pathToOpen)
@@ -417,7 +415,6 @@ class AtomApplication
openUrl: ({urlToOpen, devMode, safeMode}) ->
unless @packages?
PackageManager = require '../package-manager'
fs = require 'fs-plus'
@packages = new PackageManager
configDirPath: process.env.ATOM_HOME
devMode: devMode
+6 -11
Ver Arquivo
@@ -2,7 +2,7 @@ global.shellStartTime = Date.now()
crashReporter = require 'crash-reporter'
app = require 'app'
fs = require 'fs'
fs = require 'fs-plus'
path = require 'path'
optimist = require 'optimist'
nslog = require 'nslog'
@@ -43,10 +43,11 @@ start = ->
cwd = args.executedFrom?.toString() or process.cwd()
args.pathsToOpen = args.pathsToOpen.map (pathToOpen) ->
pathToOpen = fs.normalize(pathToOpen)
if cwd
path.resolve(cwd, pathToOpen.toString())
path.resolve(cwd, pathToOpen)
else
path.resolve(pathToOpen.toString())
path.resolve(pathToOpen)
setupCoffeeScript()
if args.devMode
@@ -77,11 +78,7 @@ setupCoffeeScript = ->
setupAtomHome = ->
return if process.env.ATOM_HOME
if process.platform is 'win32'
home = process.env.USERPROFILE
else
home = process.env.HOME
atomHome = path.join(home, '.atom')
atomHome = path.join(app.getHomeDir(), '.atom')
try
atomHome = fs.realpathSync(atomHome)
process.env.ATOM_HOME = atomHome
@@ -120,7 +117,6 @@ parseCommandLine = ->
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
options.string('socket-path')
args = options.argv
if args.help
@@ -141,7 +137,6 @@ parseCommandLine = ->
newWindow = args['new-window']
pidToKillWhenClosed = args['pid'] if args['wait']
logFile = args['log-file']
socketPath = args['socket-path']
if args['resource-path']
devMode = true
@@ -166,6 +161,6 @@ parseCommandLine = ->
# explicitly pass it by command line, see http://git.io/YC8_Ew.
process.env.PATH = args['path-environment'] if args['path-environment']
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, socketPath}
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile}
start()
+3
Ver Arquivo
@@ -48,5 +48,8 @@ class BufferedNodeProcess extends BufferedProcess
options.env ?= Object.create(process.env)
options.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = 1
args = args?.slice() ? []
args.unshift(command)
args.unshift('--no-deprecation')
super({command: node, args, options, stdout, stderr, exit})
+6 -1
Ver Arquivo
@@ -868,7 +868,12 @@ class Config
save: ->
allSettings = {'*': @settings}
allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource(@getUserConfigPath())
CSON.writeFileSync(@configFilePath, allSettings)
try
CSON.writeFileSync(@configFilePath, allSettings)
catch error
message = "Failed to save `#{path.basename(@configFilePath)}`"
detail = error.message
@notifyFailure(message, detail)
###
Section: Private methods managing global settings
+2 -2
Ver Arquivo
@@ -152,12 +152,12 @@ class PaneContainer extends Model
saveAll: ->
pane.saveItems() for pane in @getPanes()
confirmClose: ->
confirmClose: (options) ->
allSaved = true
for pane in @getPanes()
for item in pane.getItems()
unless pane.promptToSaveItem(item)
unless pane.promptToSaveItem(item, options)
allSaved = false
break
+25 -4
Ver Arquivo
@@ -437,8 +437,8 @@ class Pane extends Model
destroyInactiveItems: ->
@destroyItem(item) for item in @getItems() when item isnt @activeItem
promptToSaveItem: (item) ->
return true unless item.shouldPromptToSave?()
promptToSaveItem: (item, options={}) ->
return true unless item.shouldPromptToSave?(options)
if typeof item.getURI is 'function'
uri = item.getURI()
@@ -481,7 +481,10 @@ class Pane extends Model
itemURI = item.getUri()
if itemURI?
item.save?()
try
item.save?()
catch error
@handleSaveError(error)
nextAction?()
else
@saveItemAs(item, nextAction)
@@ -498,7 +501,10 @@ class Pane extends Model
itemPath = item.getPath?()
newItemPath = atom.showSaveDialogSync(itemPath)
if newItemPath
item.saveAs(newItemPath)
try
item.saveAs(newItemPath)
catch error
@handleSaveError(error)
nextAction?()
# Public: Save all items.
@@ -667,3 +673,18 @@ class Pane extends Model
for item in @getItems()
return false unless @promptToSaveItem(item)
true
handleSaveError: (error) ->
if error.message.endsWith('is a directory')
atom.notifications.addWarning("Unable to save file: #{error.message}")
else if error.code is 'EACCES' and error.path?
atom.notifications.addWarning("Unable to save file: Permission denied '#{error.path}'")
else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN'] and error.path?
atom.notifications.addWarning("Unable to save file '#{error.path}'", detail: error.message)
else if error.code is 'EROFS' and error.path?
atom.notifications.addWarning("Unable to save file: Read-only file system '#{error.path}'")
else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message)
fileName = errorMatch[1]
atom.notifications.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to")
else
throw error
+5 -1
Ver Arquivo
@@ -641,7 +641,11 @@ class TextEditor extends Model
# Determine whether the user should be prompted to save before closing
# this editor.
shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors()
shouldPromptToSave: ({windowCloseRequested}={}) ->
if windowCloseRequested
@isModified()
else
@isModified() and not @buffer.hasMultipleEditors()
###
Section: Reading Text
+1 -1
Ver Arquivo
@@ -52,7 +52,7 @@ class WindowEventHandler
@subscribe $(window), 'blur', -> document.body.classList.add('is-blurred')
@subscribe $(window), 'beforeunload', =>
confirmed = atom.workspace?.confirmClose()
confirmed = atom.workspace?.confirmClose(windowCloseRequested: true)
atom.hide() if confirmed and not @reloadRequested and atom.getCurrentWindow().isWebViewFocused()
@reloadRequested = false
+4 -24
Ver Arquivo
@@ -599,8 +599,8 @@ class Workspace extends Model
saveAll: ->
@paneContainer.saveAll()
confirmClose: ->
@paneContainer.confirmClose()
confirmClose: (options) ->
@paneContainer.confirmClose(options)
# Save the active pane item.
#
@@ -609,7 +609,7 @@ class Workspace extends Model
# {::saveActivePaneItemAs} # will be called instead. This method does nothing
# if the active item does not implement a `.save` method.
saveActivePaneItem: ->
@saveActivePaneItemAndReportErrors('saveActiveItem')
@getActivePane().saveActiveItem()
# Prompt the user for a path and save the active pane item to it.
#
@@ -617,27 +617,7 @@ class Workspace extends Model
# `.saveAs` on the item with the selected path. This method does nothing if
# the active item does not implement a `.saveAs` method.
saveActivePaneItemAs: ->
@saveActivePaneItemAndReportErrors('saveActiveItemAs')
saveActivePaneItemAndReportErrors: (method) ->
try
@getActivePane()[method]()
catch error
if error.message.endsWith('is a directory')
atom.notifications.addWarning("Unable to save file: #{error.message}")
else if error.code is 'EACCES' and error.path?
atom.notifications.addWarning("Unable to save file: Permission denied '#{error.path}'")
else if error.code is 'EPERM' and error.path?
atom.notifications.addWarning("Unable to save file '#{error.path}'", detail: error.message)
else if error.code is 'EBUSY' and error.path?
atom.notifications.addWarning("Unable to save file '#{error.path}'", detail: error.message)
else if error.code is 'EROFS' and error.path?
atom.notifications.addWarning("Unable to save file: Read-only file system '#{error.path}'")
else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message)
fileName = errorMatch[1]
atom.notifications.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to")
else
throw error
@getActivePane().saveActiveItemAs()
# Destroy (close) the active pane item.
#
+17
Ver Arquivo
@@ -13,6 +13,23 @@ window.onload = function() {
var fs = require('fs');
var path = require('path');
// Ensure ATOM_HOME is always set before anything else is required
if (!process.env.ATOM_HOME) {
var home;
if (process.platform === 'win32') {
home = process.env.USERPROFILE;
} else {
home = process.env.HOME;
}
var atomHome = path.join(home, '.atom');
try {
atomHome = fs.realpathSync(atomHome);
} catch (error) {
// Ignore since the path might just not exist yet.
}
process.env.ATOM_HOME = atomHome;
}
// Skip "?loadSettings=".
var rawLoadSettings = decodeURIComponent(location.search.substr(14));
var loadSettings;