Comparar commits
12 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 6430bbb460 | |||
| 362ff963fd | |||
| 61ca2e14dc | |||
| 56677e71e4 | |||
| c927101bb2 | |||
| 28f280183e | |||
| f1df254a66 | |||
| af28083a6f | |||
| 495caa7316 | |||
| d0757c87c8 | |||
| c19d99e9e2 | |||
| ab43b08739 |
+12
-2
@@ -24,8 +24,18 @@ 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.
|
||||
|
||||
Using [chocolatey](https://chocolatey.org/)? Run `cinst Atom` to install
|
||||
the latest version of Atom.
|
||||
#### 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
|
||||
|
||||
### Debian Linux (Ubuntu)
|
||||
|
||||
|
||||
@@ -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', 'build']
|
||||
ciTasks = ['output-disk-space', 'download-atom-shell', 'download-atom-shell-chromedriver', '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', 'build', 'set-version']
|
||||
defaultTasks = ['download-atom-shell', 'download-atom-shell-chromedriver', 'build', 'set-version']
|
||||
defaultTasks.push 'install' unless process.platform is 'linux'
|
||||
grunt.registerTask('default', defaultTasks)
|
||||
|
||||
@@ -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.11.0",
|
||||
"grunt-download-atom-shell": "~0.12.0",
|
||||
"grunt-lesslint": "0.13.0",
|
||||
"grunt-peg": "~1.1.0",
|
||||
"grunt-shell": "~0.3.1",
|
||||
@@ -31,6 +31,7 @@
|
||||
"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",
|
||||
|
||||
@@ -47,9 +47,9 @@ module.exports = (grunt) ->
|
||||
|
||||
{description} = grunt.file.readJSON('package.json')
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'atom.png')
|
||||
executable = path.join(shareDir, 'atom')
|
||||
installDir = path.join(installDir, '.') # To prevent "Exec=/usr/local//share/atom/atom"
|
||||
template = _.template(String(fs.readFileSync(desktopFile)))
|
||||
filled = template({description, iconName, executable})
|
||||
filled = template({description, installDir, iconName})
|
||||
|
||||
grunt.file.write(desktopInstallFile, filled)
|
||||
|
||||
|
||||
@@ -85,15 +85,27 @@ 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'
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
+3
-4
@@ -31,7 +31,7 @@
|
||||
"emissary": "^1.3.1",
|
||||
"event-kit": "^1.0.2",
|
||||
"first-mate": "^3.0.0",
|
||||
"fs-plus": "^2.5",
|
||||
"fs-plus": "^2.3.2",
|
||||
"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.134.0",
|
||||
"markdown-preview": "0.133.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.29.0",
|
||||
"timecop": "0.28.0",
|
||||
"tree-view": "0.154.0",
|
||||
"update-package-dependencies": "0.8.0",
|
||||
"welcome": "0.21.0",
|
||||
@@ -125,7 +125,6 @@
|
||||
"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",
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
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 ''
|
||||
@@ -666,23 +666,6 @@ 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()
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
require('fs').existsSync('hi');
|
||||
process.stdout.write('hi');
|
||||
externo
-1
@@ -1 +0,0 @@
|
||||
process.stdout.write(process.argv[2]);
|
||||
Arquivo executável
+36
@@ -0,0 +1,36 @@
|
||||
#!/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[@]}"
|
||||
@@ -0,0 +1,107 @@
|
||||
# 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()
|
||||
@@ -383,25 +383,6 @@ 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
|
||||
|
||||
@@ -423,25 +404,6 @@ 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")])
|
||||
|
||||
@@ -305,13 +305,13 @@ window.waitsForPromise = (args...) ->
|
||||
window.waitsFor timeout, (moveOn) ->
|
||||
promise = fn()
|
||||
if shouldReject
|
||||
promise.catch(moveOn)
|
||||
(promise.catch ? promise.thenCatch).call(promise, moveOn)
|
||||
promise.then ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be rejected, but it was resolved")
|
||||
moveOn()
|
||||
else
|
||||
promise.then(moveOn)
|
||||
promise.catch (error) ->
|
||||
(promise.catch ? promise.thenCatch).call promise, (error) ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with #{jasmine.pp(error)}")
|
||||
moveOn()
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{$, $$} = 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'
|
||||
|
||||
@@ -56,7 +54,7 @@ describe "Window", ->
|
||||
jasmine.unspy(TextEditor.prototype, "shouldPromptToSave")
|
||||
beforeUnloadEvent = $.Event(new Event('beforeunload'))
|
||||
|
||||
describe "when pane items are modified", ->
|
||||
describe "when pane items are are modified", ->
|
||||
it "prompts user to save and calls atom.workspace.confirmClose", ->
|
||||
editor = null
|
||||
spyOn(atom.workspace, 'confirmClose').andCallThrough()
|
||||
@@ -94,25 +92,6 @@ 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()
|
||||
|
||||
@@ -955,14 +955,9 @@ 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(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("'/some/file' is a directory")
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
@@ -971,7 +966,7 @@ describe "Workspace", ->
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the directory cannot be written to", ->
|
||||
spyOn(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("ENOTDIR, not a directory '/Some/dir/and-a-file.js'")
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
@@ -980,7 +975,7 @@ describe "Workspace", ->
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the user does not have permission", ->
|
||||
spyOn(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
error = new Error("EACCES, permission denied '/Some/dir/and-a-file.js'")
|
||||
error.code = 'EACCES'
|
||||
error.path = '/Some/dir/and-a-file.js'
|
||||
@@ -992,14 +987,14 @@ describe "Workspace", ->
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the operation is not permitted", ->
|
||||
spyOn(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').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(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').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'
|
||||
@@ -1014,7 +1009,7 @@ describe "Workspace", ->
|
||||
expect(notificaiton.getMessage()).toContain 'Unable to save'
|
||||
|
||||
it "emits a warning notification when the file system is read-only", ->
|
||||
spyOn(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').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'
|
||||
@@ -1029,7 +1024,7 @@ describe "Workspace", ->
|
||||
expect(notification.getMessage()).toContain 'Unable to save'
|
||||
|
||||
it "emits a warning notification when the file cannot be saved", ->
|
||||
spyOn(editor, 'save').andCallFake ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("no one knows")
|
||||
|
||||
save = -> atom.workspace.saveActivePaneItem()
|
||||
|
||||
@@ -5,7 +5,7 @@ AutoUpdateManager = require './auto-update-manager'
|
||||
BrowserWindow = require 'browser-window'
|
||||
Menu = require 'menu'
|
||||
app = require 'app'
|
||||
fs = require 'fs-plus'
|
||||
fs = require 'fs'
|
||||
ipc = require 'ipc'
|
||||
path = require 'path'
|
||||
os = require 'os'
|
||||
@@ -14,7 +14,7 @@ url = require 'url'
|
||||
{EventEmitter} = require 'events'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
socketPath =
|
||||
DefaultSocketPath =
|
||||
if process.platform is 'win32'
|
||||
'\\\\.\\pipe\\atom-sock'
|
||||
else
|
||||
@@ -31,17 +31,20 @@ 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 socketPath) or options.test
|
||||
if (process.platform isnt 'win32' and not fs.existsSync options.socketPath) or options.test
|
||||
createAtomApplication()
|
||||
return
|
||||
|
||||
client = net.connect {path: socketPath}, ->
|
||||
|
||||
client = net.connect {path: options.socketPath}, ->
|
||||
client.write JSON.stringify(options), ->
|
||||
client.end()
|
||||
app.terminate()
|
||||
@@ -57,7 +60,7 @@ class AtomApplication
|
||||
exit: (status) -> app.exit(status)
|
||||
|
||||
constructor: (options) ->
|
||||
{@resourcePath, @version, @devMode, @safeMode} = options
|
||||
{@resourcePath, @version, @devMode, @safeMode, @socketPath} = options
|
||||
|
||||
# Normalize to make sure drive letter case is consistent on Windows
|
||||
@resourcePath = path.normalize(@resourcePath) if @resourcePath
|
||||
@@ -119,15 +122,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
|
||||
@@ -342,7 +345,6 @@ 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)
|
||||
@@ -415,6 +417,7 @@ 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
|
||||
|
||||
@@ -2,7 +2,7 @@ global.shellStartTime = Date.now()
|
||||
|
||||
crashReporter = require 'crash-reporter'
|
||||
app = require 'app'
|
||||
fs = require 'fs-plus'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
optimist = require 'optimist'
|
||||
nslog = require 'nslog'
|
||||
@@ -43,11 +43,10 @@ start = ->
|
||||
|
||||
cwd = args.executedFrom?.toString() or process.cwd()
|
||||
args.pathsToOpen = args.pathsToOpen.map (pathToOpen) ->
|
||||
pathToOpen = fs.normalize(pathToOpen)
|
||||
if cwd
|
||||
path.resolve(cwd, pathToOpen)
|
||||
path.resolve(cwd, pathToOpen.toString())
|
||||
else
|
||||
path.resolve(pathToOpen)
|
||||
path.resolve(pathToOpen.toString())
|
||||
|
||||
setupCoffeeScript()
|
||||
if args.devMode
|
||||
@@ -78,7 +77,11 @@ setupCoffeeScript = ->
|
||||
setupAtomHome = ->
|
||||
return if process.env.ATOM_HOME
|
||||
|
||||
atomHome = path.join(app.getHomeDir(), '.atom')
|
||||
if process.platform is 'win32'
|
||||
home = process.env.USERPROFILE
|
||||
else
|
||||
home = process.env.HOME
|
||||
atomHome = path.join(home, '.atom')
|
||||
try
|
||||
atomHome = fs.realpathSync(atomHome)
|
||||
process.env.ATOM_HOME = atomHome
|
||||
@@ -117,6 +120,7 @@ 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
|
||||
@@ -137,6 +141,7 @@ 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
|
||||
@@ -161,6 +166,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}
|
||||
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, socketPath}
|
||||
|
||||
start()
|
||||
|
||||
@@ -48,8 +48,5 @@ 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})
|
||||
|
||||
+1
-6
@@ -868,12 +868,7 @@ class Config
|
||||
save: ->
|
||||
allSettings = {'*': @settings}
|
||||
allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource(@getUserConfigPath())
|
||||
try
|
||||
CSON.writeFileSync(@configFilePath, allSettings)
|
||||
catch error
|
||||
message = "Failed to save `#{path.basename(@configFilePath)}`"
|
||||
detail = error.message
|
||||
@notifyFailure(message, detail)
|
||||
CSON.writeFileSync(@configFilePath, allSettings)
|
||||
|
||||
###
|
||||
Section: Private methods managing global settings
|
||||
|
||||
@@ -152,12 +152,12 @@ class PaneContainer extends Model
|
||||
saveAll: ->
|
||||
pane.saveItems() for pane in @getPanes()
|
||||
|
||||
confirmClose: (options) ->
|
||||
confirmClose: ->
|
||||
allSaved = true
|
||||
|
||||
for pane in @getPanes()
|
||||
for item in pane.getItems()
|
||||
unless pane.promptToSaveItem(item, options)
|
||||
unless pane.promptToSaveItem(item)
|
||||
allSaved = false
|
||||
break
|
||||
|
||||
|
||||
+4
-25
@@ -437,8 +437,8 @@ class Pane extends Model
|
||||
destroyInactiveItems: ->
|
||||
@destroyItem(item) for item in @getItems() when item isnt @activeItem
|
||||
|
||||
promptToSaveItem: (item, options={}) ->
|
||||
return true unless item.shouldPromptToSave?(options)
|
||||
promptToSaveItem: (item) ->
|
||||
return true unless item.shouldPromptToSave?()
|
||||
|
||||
if typeof item.getURI is 'function'
|
||||
uri = item.getURI()
|
||||
@@ -481,10 +481,7 @@ class Pane extends Model
|
||||
itemURI = item.getUri()
|
||||
|
||||
if itemURI?
|
||||
try
|
||||
item.save?()
|
||||
catch error
|
||||
@handleSaveError(error)
|
||||
item.save?()
|
||||
nextAction?()
|
||||
else
|
||||
@saveItemAs(item, nextAction)
|
||||
@@ -501,10 +498,7 @@ class Pane extends Model
|
||||
itemPath = item.getPath?()
|
||||
newItemPath = atom.showSaveDialogSync(itemPath)
|
||||
if newItemPath
|
||||
try
|
||||
item.saveAs(newItemPath)
|
||||
catch error
|
||||
@handleSaveError(error)
|
||||
item.saveAs(newItemPath)
|
||||
nextAction?()
|
||||
|
||||
# Public: Save all items.
|
||||
@@ -673,18 +667,3 @@ 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
|
||||
|
||||
@@ -641,11 +641,7 @@ class TextEditor extends Model
|
||||
|
||||
# Determine whether the user should be prompted to save before closing
|
||||
# this editor.
|
||||
shouldPromptToSave: ({windowCloseRequested}={}) ->
|
||||
if windowCloseRequested
|
||||
@isModified()
|
||||
else
|
||||
@isModified() and not @buffer.hasMultipleEditors()
|
||||
shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors()
|
||||
|
||||
###
|
||||
Section: Reading Text
|
||||
|
||||
@@ -52,7 +52,7 @@ class WindowEventHandler
|
||||
@subscribe $(window), 'blur', -> document.body.classList.add('is-blurred')
|
||||
|
||||
@subscribe $(window), 'beforeunload', =>
|
||||
confirmed = atom.workspace?.confirmClose(windowCloseRequested: true)
|
||||
confirmed = atom.workspace?.confirmClose()
|
||||
atom.hide() if confirmed and not @reloadRequested and atom.getCurrentWindow().isWebViewFocused()
|
||||
@reloadRequested = false
|
||||
|
||||
|
||||
+24
-4
@@ -599,8 +599,8 @@ class Workspace extends Model
|
||||
saveAll: ->
|
||||
@paneContainer.saveAll()
|
||||
|
||||
confirmClose: (options) ->
|
||||
@paneContainer.confirmClose(options)
|
||||
confirmClose: ->
|
||||
@paneContainer.confirmClose()
|
||||
|
||||
# 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: ->
|
||||
@getActivePane().saveActiveItem()
|
||||
@saveActivePaneItemAndReportErrors('saveActiveItem')
|
||||
|
||||
# Prompt the user for a path and save the active pane item to it.
|
||||
#
|
||||
@@ -617,7 +617,27 @@ 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: ->
|
||||
@getActivePane().saveActiveItemAs()
|
||||
@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
|
||||
|
||||
# Destroy (close) the active pane item.
|
||||
#
|
||||
|
||||
@@ -13,23 +13,6 @@ 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;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário