From 6d0c708a7bffa432e7fd63413464d4d1d58eca27 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Sun, 20 Mar 2016 14:54:22 +0900 Subject: [PATCH 001/160] :racehorse: wrap loop of setDefaults in transact --- src/config.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 66f07516e..595cab280 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -958,9 +958,10 @@ class Config setDefaults: (keyPath, defaults) -> if defaults? and isPlainObject(defaults) keys = splitKeyPath(keyPath) - for key, childValue of defaults - continue unless defaults.hasOwnProperty(key) - @setDefaults(keys.concat([key]).join('.'), childValue) + @transact => + for key, childValue of defaults + continue unless defaults.hasOwnProperty(key) + @setDefaults(keys.concat([key]).join('.'), childValue) else try defaults = @makeValueConformToSchema(keyPath, defaults) From 3836907ee36219d32f5e12e5df07320b019fed87 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 3 Jun 2016 19:04:16 -0700 Subject: [PATCH 002/160] :arrow_up: apm@1.11.0 Signed-off-by: Katrina Uychaco --- apm/package.json | 2 +- build/package.json | 2 +- script/bootstrap | 7 +------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/apm/package.json b/apm/package.json index d4fcc851a..e547f494f 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.10.0" + "atom-package-manager": "1.11.0" } } diff --git a/build/package.json b/build/package.json index 2f8d88d8a..d0fd27fe1 100644 --- a/build/package.json +++ b/build/package.json @@ -32,7 +32,7 @@ "grunt-standard": "^2.0.0", "legal-eagle": "~0.13.0", "minidump": "~0.9", - "npm": "2.13.3", + "npm": "3.9.5", "rcedit": "~0.3.0", "request": "~2.27.0", "rimraf": "~2.2.2", diff --git a/script/bootstrap b/script/bootstrap index 3b9a35735..8e63de378 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -75,7 +75,7 @@ function bootstrap() { var buildInstallCommand = initialNpmCommand + npmFlags + 'install'; var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')}; - var apmInstallCommand = npmPath + npmFlags + '--target=0.10.40 ' + 'install'; + var apmInstallCommand = npmPath + npmFlags + '--target=4.4.5 --global-style ' + 'install'; var apmInstallOptions = {cwd: apmInstallPath}; var moduleInstallCommand = apmPath + ' install' + apmFlags; var dedupeApmCommand = apmPath + ' dedupe' + apmFlags; @@ -122,11 +122,6 @@ function bootstrap() { message: 'Installing apm...', options: apmInstallOptions }, - { - command: apmPath + ' clean' + apmFlags, - message: 'Deleting old packages...', - options: moduleInstallOptions - }, { command: moduleInstallCommand, options: moduleInstallOptions From 0ea0f15687b97a668013712d5d25fa006048fc5e Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 3 Jun 2016 19:20:28 -0700 Subject: [PATCH 003/160] :arrow_up: apm@1.11.1 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index e547f494f..335531ce3 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.11.0" + "atom-package-manager": "1.11.1" } } From 96db9a6dfadffef2214e6187ed941670d5ca71be Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 11 Jun 2016 02:05:58 -0700 Subject: [PATCH 004/160] :arrow_up: ohnogit@0.0.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec051cb21..bf37cc459 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "mocha": "2.5.1", "normalize-package-data": "^2.0.0", "nslog": "^3", - "ohnogit": "0.0.13", + "ohnogit": "0.0.14", "oniguruma": "^5", "pathwatcher": "~6.5", "property-accessors": "^1.1.3", From 65cb6c86c09a97386a677451c6f6d95940dc64f1 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 11 Jun 2016 02:06:23 -0700 Subject: [PATCH 005/160] :arrow_up: apm@1.11.2 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 335531ce3..afbcdada3 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.11.1" + "atom-package-manager": "1.11.2" } } From c19ed790665ad123d6fb52e79051a68534befe65 Mon Sep 17 00:00:00 2001 From: Ross Allen Date: Wed, 8 Jun 2016 16:36:37 -0700 Subject: [PATCH 006/160] Complete documentation for Notification creation Notifications support several options that were yet to be documented: `buttons`, `description`, and `stack`. Add descriptions for each option and its defaults (where applicable, e.g. .buttons.className). `stack` is technically available on all notification types, but it doesn't make sense to use it on types other than 'error' and 'fatal'. Therefore it's documented only in those two cases. The usage and expected display, like preformatted vs. Markdown, taken from [atom/notifications/lib/notification-element.coffee][1]. [1]: https://github.com/atom/notifications/blob/v0.64.1/lib/notification-element.coffee --- src/notification-manager.coffee | 74 ++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/src/notification-manager.coffee b/src/notification-manager.coffee index 3d8b1895c..7b712e6bf 100644 --- a/src/notification-manager.coffee +++ b/src/notification-manager.coffee @@ -33,8 +33,18 @@ class NotificationManager # # * `message` A {String} message # * `options` (optional) An options {Object} with the following keys: - # * `detail` (optional) A {String} with additional details about the - # notification. + # * `buttons` (optional) An {Array} of {Object} where each {Object} has the + # following options: + # * `className` (optional) {String} additional class name add to the + # button. It will already receive `btn btn-success`. + # * `onClick` (optional) {Function} callback to call when the button is + # clicked. The context will be set to the {NotificationElement} + # instance. + # * `text` {String} inner text for the button + # * `description` (optional) A {String} that will be rendered as Markdown + # to describe the notification. + # * `detail` (optional) A preformatted {String} that will be rendered as + # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -46,8 +56,18 @@ class NotificationManager # # * `message` A {String} message # * `options` (optional) An options {Object} with the following keys: - # * `detail` (optional) A {String} with additional details about the - # notification. + # * `buttons` (optional) An {Array} of {Object} where each {Object} has the + # following options: + # * `className` (optional) {String} additional class name add to the + # button. It will already receive `btn btn-info`. + # * `onClick` (optional) {Function} callback to call when the button is + # clicked. The context will be set to the {NotificationElement} + # instance. + # * `text` {String} inner text for the button + # * `description` (optional) A {String} that will be rendered as Markdown + # to describe the notification. + # * `detail` (optional) A preformatted {String} that will be rendered as + # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -59,8 +79,18 @@ class NotificationManager # # * `message` A {String} message # * `options` (optional) An options {Object} with the following keys: - # * `detail` (optional) A {String} with additional details about the - # notification. + # * `buttons` (optional) An {Array} of {Object} where each {Object} has the + # following options: + # * `className` (optional) {String} additional class name add to the + # button. It will already receive `btn btn-warning`. + # * `onClick` (optional) {Function} callback to call when the button is + # clicked. The context will be set to the {NotificationElement} + # instance. + # * `text` {String} inner text for the button + # * `description` (optional) A {String} that will be rendered as Markdown + # to describe the notification. + # * `detail` (optional) A preformatted {String} that will be rendered as + # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -72,12 +102,24 @@ class NotificationManager # # * `message` A {String} message # * `options` (optional) An options {Object} with the following keys: - # * `detail` (optional) A {String} with additional details about the - # notification. + # * `buttons` (optional) An {Array} of {Object} where each {Object} has the + # following options: + # * `className` (optional) {String} additional class name add to the + # button. It will already receive `btn btn-error`. + # * `onClick` (optional) {Function} callback to call when the button is + # clicked. The context will be set to the {NotificationElement} + # instance. + # * `text` {String} inner text for the button + # * `description` (optional) A {String} that will be rendered as Markdown + # to describe the notification. + # * `detail` (optional) A preformatted {String} that will be rendered as + # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display # in the notification header. Defaults to `'flame'`. + # * `stack` (optional) A preformatted {String} with stack trace information + # describing the location of the error. addError: (message, options) -> @addNotification(new Notification('error', message, options)) @@ -85,12 +127,24 @@ class NotificationManager # # * `message` A {String} message # * `options` (optional) An options {Object} with the following keys: - # * `detail` (optional) A {String} with additional details about the - # notification. + # * `buttons` (optional) An {Array} of {Object} where each {Object} has the + # following options: + # * `className` (optional) {String} additional class name add to the + # button. It will already receive `btn btn-error`. + # * `onClick` (optional) {Function} callback to call when the button is + # clicked. The context will be set to the {NotificationElement} + # instance. + # * `text` {String} inner text for the button + # * `description` (optional) A {String} that will be rendered as Markdown + # to describe the notification. + # * `detail` (optional) A preformatted {String} that will be rendered as + # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display # in the notification header. Defaults to `'bug'`. + # * `stack` (optional) A preformatted {String} with stack trace information + # describing the location of the error. addFatalError: (message, options) -> @addNotification(new Notification('fatal', message, options)) From 86cdc61ff0ac3efd2b077edc58f0d777a3f00d86 Mon Sep 17 00:00:00 2001 From: Ross Allen Date: Tue, 14 Jun 2016 07:34:32 -0700 Subject: [PATCH 007/160] Correctly reference `onDidClick`, not `onClick` --- src/notification-manager.coffee | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/notification-manager.coffee b/src/notification-manager.coffee index 7b712e6bf..aaeb75c15 100644 --- a/src/notification-manager.coffee +++ b/src/notification-manager.coffee @@ -37,9 +37,9 @@ class NotificationManager # following options: # * `className` (optional) {String} additional class name add to the # button. It will already receive `btn btn-success`. - # * `onClick` (optional) {Function} callback to call when the button is - # clicked. The context will be set to the {NotificationElement} - # instance. + # * `onDidClick` (optional) {Function} callback to call when the button + # has been clicked. The context will be set to the + # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A {String} that will be rendered as Markdown # to describe the notification. @@ -60,9 +60,9 @@ class NotificationManager # following options: # * `className` (optional) {String} additional class name add to the # button. It will already receive `btn btn-info`. - # * `onClick` (optional) {Function} callback to call when the button is - # clicked. The context will be set to the {NotificationElement} - # instance. + # * `onDidClick` (optional) {Function} callback to call when the button + # has been clicked. The context will be set to the + # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A {String} that will be rendered as Markdown # to describe the notification. @@ -83,9 +83,9 @@ class NotificationManager # following options: # * `className` (optional) {String} additional class name add to the # button. It will already receive `btn btn-warning`. - # * `onClick` (optional) {Function} callback to call when the button is - # clicked. The context will be set to the {NotificationElement} - # instance. + # * `onDidClick` (optional) {Function} callback to call when the button + # has been clicked. The context will be set to the + # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A {String} that will be rendered as Markdown # to describe the notification. @@ -106,9 +106,9 @@ class NotificationManager # following options: # * `className` (optional) {String} additional class name add to the # button. It will already receive `btn btn-error`. - # * `onClick` (optional) {Function} callback to call when the button is - # clicked. The context will be set to the {NotificationElement} - # instance. + # * `onDidClick` (optional) {Function} callback to call when the button + # has been clicked. The context will be set to the + # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A {String} that will be rendered as Markdown # to describe the notification. @@ -131,9 +131,9 @@ class NotificationManager # following options: # * `className` (optional) {String} additional class name add to the # button. It will already receive `btn btn-error`. - # * `onClick` (optional) {Function} callback to call when the button is - # clicked. The context will be set to the {NotificationElement} - # instance. + # * `onDidClick` (optional) {Function} callback to call when the button + # has been clicked. The context will be set to the + # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A {String} that will be rendered as Markdown # to describe the notification. From e67ebf3639e3c48ce75d0d306bca611319cc8afa Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 13 Jun 2016 11:02:41 -0700 Subject: [PATCH 008/160] Change up native build options --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7b6113aa0..05d040dce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ branches: env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 + - C_INCLUDE_PATH=/usr/include/$(gcc -print-multiarch) compiler: clang @@ -51,3 +52,4 @@ addons: - git - libgnome-keyring-dev - fakeroot + - gcc-multilib From 496539208bb0a434a2a7e51394f5c58ba8786ce9 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 13:40:40 -0700 Subject: [PATCH 009/160] Only read actual package.json files from disk in compile-packages-slug task --- build/tasks/compile-packages-slug-task.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/tasks/compile-packages-slug-task.coffee b/build/tasks/compile-packages-slug-task.coffee index 7317f158a..f6f297bec 100644 --- a/build/tasks/compile-packages-slug-task.coffee +++ b/build/tasks/compile-packages-slug-task.coffee @@ -40,6 +40,8 @@ module.exports = (grunt) -> continue if path.basename(moduleDirectory) is '.bin' metadataPath = path.join(moduleDirectory, 'package.json') + continue unless fs.existsSync(metadataPath) + metadata = grunt.file.readJSON(metadataPath) continue unless metadata?.engines?.atom? From 3b849241593f9cac3470ecf320afe1169818886b Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 13:50:44 -0700 Subject: [PATCH 010/160] :arrow_up: Node.js@4.4.5 on Appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 51e074a4c..9a396f8cf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,7 +18,7 @@ environment: secure: Q7vxmSq0bVCLTTRPzXw5ZhPTe7XYhWxX0tQV6neEkddTH6pZkOYNmSCG6VnMX2f+ matrix: - - NODE_VERSION: 0.10.35 + - NODE_VERSION: 4.4.5 install: - SET PATH=C:\Program Files\Atom\resources\cli;%PATH% From 3c717626d776e18b4ed878b18d15e2178fa8a903 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 14:24:27 -0700 Subject: [PATCH 011/160] :arrow_up: apm@1.11.3 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index afbcdada3..614438ec7 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.11.2" + "atom-package-manager": "1.11.3" } } From 4fd463a2fbd10a4eef4d538436d41b4293414a3f Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 14:38:51 -0700 Subject: [PATCH 012/160] Don't suppress build output when ATOM_NOISY_BUILD is set --- script/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/bootstrap b/script/bootstrap index 8e63de378..6fcf8fef0 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -97,7 +97,7 @@ function bootstrap() { } var moduleInstallOptions = {env: moduleInstallEnv}; - if (process.argv.indexOf('--no-quiet') === -1) { + if (process.argv.indexOf('--no-quiet') === -1 || process.env.ATOM_NOISY_BUILD) { buildInstallCommand += ' --loglevel error'; apmInstallCommand += ' --loglevel error'; moduleInstallCommand += ' --loglevel error'; From acb0ae9225e75f8083b0e76a7c7984e434392600 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 14:39:12 -0700 Subject: [PATCH 013/160] Set ATOM_NOISY_BUILD on Appveyor --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 9a396f8cf..ef65771f2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,7 @@ environment: ATOM_DEV_RESOURCE_PATH: c:\projects\atom ATOM_ACCESS_TOKEN: secure: Q7vxmSq0bVCLTTRPzXw5ZhPTe7XYhWxX0tQV6neEkddTH6pZkOYNmSCG6VnMX2f+ + ATOM_NOISY_BUILD: 1 matrix: - NODE_VERSION: 4.4.5 From dc659ff9b3aa9119e165dc13063e04d97a794806 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 15:17:05 -0700 Subject: [PATCH 014/160] :arrow_up: apm@1.11.4 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 614438ec7..3bf1fe769 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.11.3" + "atom-package-manager": "1.11.4" } } From fa7d1d66875421372bcceb0f1a07e818a4af5e72 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 15:31:59 -0700 Subject: [PATCH 015/160] Use g++ 4.8 on travis --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 05d040dce..d28157b37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ branches: env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 - - C_INCLUDE_PATH=/usr/include/$(gcc -print-multiarch) + - CXX=g++-4.8 compiler: clang @@ -47,9 +47,11 @@ notifications: addons: apt: + sources: + - ubuntu-toolchain-r-test packages: - build-essential - git - libgnome-keyring-dev - fakeroot - - gcc-multilib + - g++-4.8 From 6af247e601dd9c180fa9c6e3583b4c39e5e5fb8e Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 16:53:24 -0700 Subject: [PATCH 016/160] Only test on Node 4 on Travis --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d28157b37..6bd3c78cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,14 +14,12 @@ compiler: clang matrix: include: - - os: linux - env: NODE_VERSION=0.12 - os: linux env: NODE_VERSION=4 - os: osx - env: ATOM_SPECS_TASK=core NODE_VERSION=0.12 + env: ATOM_SPECS_TASK=core NODE_VERSION=4 - os: osx - env: ATOM_SPECS_TASK=packages NODE_VERSION=0.12 + env: ATOM_SPECS_TASK=packages NODE_VERSION=4 sudo: false From c6fbae521b4d5262808fa08131cda66a98d9e427 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 14 Jun 2016 17:59:29 -0700 Subject: [PATCH 017/160] Use --delete-prefix with nvm use --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6bd3c78cb..563f8168b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ install: - git clone https://github.com/creationix/nvm.git /tmp/.nvm - source /tmp/.nvm/nvm.sh - nvm install $NODE_VERSION - - nvm use $NODE_VERSION + - nvm use --delete-prefix $NODE_VERSION script: script/cibuild From 752359b33268ddc924b409f497bb90eab146bbf5 Mon Sep 17 00:00:00 2001 From: Ross Allen Date: Tue, 21 Jun 2016 08:22:05 -0700 Subject: [PATCH 018/160] Clarify `buttonClass` and `description` --- src/notification-manager.coffee | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/notification-manager.coffee b/src/notification-manager.coffee index aaeb75c15..a22ca0256 100644 --- a/src/notification-manager.coffee +++ b/src/notification-manager.coffee @@ -35,14 +35,14 @@ class NotificationManager # * `options` (optional) An options {Object} with the following keys: # * `buttons` (optional) An {Array} of {Object} where each {Object} has the # following options: - # * `className` (optional) {String} additional class name add to the - # button. It will already receive `btn btn-success`. + # * `className` (optional) {String} a class name to add to the button's + # default class name (`btn btn-success`). # * `onDidClick` (optional) {Function} callback to call when the button # has been clicked. The context will be set to the # {NotificationElement} instance. # * `text` {String} inner text for the button - # * `description` (optional) A {String} that will be rendered as Markdown - # to describe the notification. + # * `description` (optional) A Markdown {String} containing a longer + # description about the notification. # * `detail` (optional) A preformatted {String} that will be rendered as # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this @@ -58,14 +58,14 @@ class NotificationManager # * `options` (optional) An options {Object} with the following keys: # * `buttons` (optional) An {Array} of {Object} where each {Object} has the # following options: - # * `className` (optional) {String} additional class name add to the - # button. It will already receive `btn btn-info`. + # * `className` (optional) {String} a class name to add to the button's + # default class name (`btn btn-info`). # * `onDidClick` (optional) {Function} callback to call when the button # has been clicked. The context will be set to the # {NotificationElement} instance. # * `text` {String} inner text for the button - # * `description` (optional) A {String} that will be rendered as Markdown - # to describe the notification. + # * `description` (optional) A Markdown {String} containing a longer + # description about the notification. # * `detail` (optional) A preformatted {String} that will be rendered as # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this @@ -81,14 +81,14 @@ class NotificationManager # * `options` (optional) An options {Object} with the following keys: # * `buttons` (optional) An {Array} of {Object} where each {Object} has the # following options: - # * `className` (optional) {String} additional class name add to the - # button. It will already receive `btn btn-warning`. + # * `className` (optional) {String} a class name to add to the button's + # default class name (`btn btn-warning`). # * `onDidClick` (optional) {Function} callback to call when the button # has been clicked. The context will be set to the # {NotificationElement} instance. # * `text` {String} inner text for the button - # * `description` (optional) A {String} that will be rendered as Markdown - # to describe the notification. + # * `description` (optional) A Markdown {String} containing a longer + # description about the notification. # * `detail` (optional) A preformatted {String} that will be rendered as # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this @@ -104,14 +104,14 @@ class NotificationManager # * `options` (optional) An options {Object} with the following keys: # * `buttons` (optional) An {Array} of {Object} where each {Object} has the # following options: - # * `className` (optional) {String} additional class name add to the - # button. It will already receive `btn btn-error`. + # * `className` (optional) {String} a class name to add to the button's + # default class name (`btn btn-error`). # * `onDidClick` (optional) {Function} callback to call when the button # has been clicked. The context will be set to the # {NotificationElement} instance. # * `text` {String} inner text for the button - # * `description` (optional) A {String} that will be rendered as Markdown - # to describe the notification. + # * `description` (optional) A Markdown {String} containing a longer + # description about the notification. # * `detail` (optional) A preformatted {String} that will be rendered as # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this @@ -129,14 +129,14 @@ class NotificationManager # * `options` (optional) An options {Object} with the following keys: # * `buttons` (optional) An {Array} of {Object} where each {Object} has the # following options: - # * `className` (optional) {String} additional class name add to the - # button. It will already receive `btn btn-error`. + # * `className` (optional) {String} a class name to add to the button's + # default class name (`btn btn-error`). # * `onDidClick` (optional) {Function} callback to call when the button # has been clicked. The context will be set to the # {NotificationElement} instance. # * `text` {String} inner text for the button - # * `description` (optional) A {String} that will be rendered as Markdown - # to describe the notification. + # * `description` (optional) A Markdown {String} containing a longer + # description about the notification. # * `detail` (optional) A preformatted {String} that will be rendered as # plain text with details about the notification. # * `dismissable` (optional) A {Boolean} indicating whether this From 341a9602b293b4fdcf69f62ced2c50fc6f615eae Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Mon, 27 Jun 2016 22:34:37 -0700 Subject: [PATCH 019/160] Use in-path 7z on AppVeyor, tidy-up publish --- build/tasks/publish-build-task.coffee | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 0a18c9c23..2802f827d 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -11,6 +11,7 @@ AWS = require 'aws-sdk' grunt = null token = process.env.ATOM_ACCESS_TOKEN +repo = process.env.ATOM_REPO ? 'atom/atom' defaultHeaders = Authorization: "token #{token}" 'User-Agent': 'Atom' @@ -119,7 +120,8 @@ logError = (message, error, details) -> zipAssets = (buildDir, assets, callback) -> zip = (directory, sourcePath, assetName, callback) -> if process.platform is 'win32' - zipCommand = "C:/psmodules/7z.exe a -r #{assetName} \"#{sourcePath}\"" + sevenZipPath = if process.env.JANKY_SHA1? then "C:/psmodules/" else "" + zipCommand = "#{sevenZipPath}7z.exe a -r \"#{assetName}\" \"#{sourcePath}\"" else zipCommand = "zip -r --symlinks '#{assetName}' '#{sourcePath}'" options = {cwd: directory, maxBuffer: Infinity} @@ -134,10 +136,10 @@ zipAssets = (buildDir, assets, callback) -> async.parallel(tasks, callback) getAtomDraftRelease = (isPrerelease, branchName, callback) -> - atomRepo = new GitHub({repo: 'atom/atom', token}) + atomRepo = new GitHub({repo: repo, token}) atomRepo.getReleases {prerelease: isPrerelease}, (error, releases=[]) -> if error? - logError('Fetching atom/atom releases failed', error, releases) + logError("Fetching #{repo} #{if isPrerelease then "pre" else "" }releases failed", error, releases) callback(error) else [firstDraft] = releases.filter ({draft}) -> draft @@ -160,7 +162,7 @@ getAtomDraftRelease = (isPrerelease, branchName, callback) -> createAtomDraftRelease = (isPrerelease, branchName, callback) -> {version} = require('../../package.json') options = - uri: 'https://api.github.com/repos/atom/atom/releases' + uri: "https://api.github.com/repos/#{repo}/releases" method: 'POST' headers: defaultHeaders json: @@ -177,7 +179,7 @@ createAtomDraftRelease = (isPrerelease, branchName, callback) -> request options, (error, response, body='') -> if error? or response.statusCode isnt 201 - logError("Creating atom/atom draft release failed", error, body) + logError("Creating #{repo} draft release failed", error, body) callback(error ? new Error(response.statusCode)) else callback(null, body) From 048c1192651c4ee421b711aa87461a27b027a1c2 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 28 Jun 2016 16:03:43 -0700 Subject: [PATCH 020/160] Don't use g++-4.8 --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 563f8168b..cf0c07186 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ branches: env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 - - CXX=g++-4.8 compiler: clang @@ -52,4 +51,3 @@ addons: - git - libgnome-keyring-dev - fakeroot - - g++-4.8 From 4558833ef6869030e56ee3b009a3220a518a5f36 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Wed, 29 Jun 2016 13:31:36 -0700 Subject: [PATCH 021/160] Include gcc-multilib on travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cf0c07186..58f82c013 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,3 +51,4 @@ addons: - git - libgnome-keyring-dev - fakeroot + - gcc-multilib From 7e75b861d8b9b26382764bea587b676a53c7d8a1 Mon Sep 17 00:00:00 2001 From: Ross Allen Date: Thu, 30 Jun 2016 15:57:22 -0700 Subject: [PATCH 022/160] Describe whitespace in `detail` and `description` `detail` is rendered as preformatted text in core themes. `description` is rendered as Markdown. --- src/notification-manager.coffee | 40 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/notification-manager.coffee b/src/notification-manager.coffee index a22ca0256..1cb144bdc 100644 --- a/src/notification-manager.coffee +++ b/src/notification-manager.coffee @@ -42,9 +42,11 @@ class NotificationManager # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A Markdown {String} containing a longer - # description about the notification. - # * `detail` (optional) A preformatted {String} that will be rendered as - # plain text with details about the notification. + # description about the notification. By default, this **will not** + # preserve newlines and whitespace when it is rendered. + # * `detail` (optional) A plain-text {String} containing additional details + # about the notification. By default, this **will** preserve newlines + # and whitespace when it is rendered. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -65,9 +67,11 @@ class NotificationManager # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A Markdown {String} containing a longer - # description about the notification. - # * `detail` (optional) A preformatted {String} that will be rendered as - # plain text with details about the notification. + # description about the notification. By default, this **will not** + # preserve newlines and whitespace when it is rendered. + # * `detail` (optional) A plain-text {String} containing additional details + # about the notification. By default, this **will** preserve newlines + # and whitespace when it is rendered. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -88,9 +92,11 @@ class NotificationManager # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A Markdown {String} containing a longer - # description about the notification. - # * `detail` (optional) A preformatted {String} that will be rendered as - # plain text with details about the notification. + # description about the notification. By default, this **will not** + # preserve newlines and whitespace when it is rendered. + # * `detail` (optional) A plain-text {String} containing additional details + # about the notification. By default, this **will** preserve newlines + # and whitespace when it is rendered. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -111,9 +117,11 @@ class NotificationManager # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A Markdown {String} containing a longer - # description about the notification. - # * `detail` (optional) A preformatted {String} that will be rendered as - # plain text with details about the notification. + # description about the notification. By default, this **will not** + # preserve newlines and whitespace when it is rendered. + # * `detail` (optional) A plain-text {String} containing additional details + # about the notification. By default, this **will** preserve newlines + # and whitespace when it is rendered. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display @@ -136,9 +144,11 @@ class NotificationManager # {NotificationElement} instance. # * `text` {String} inner text for the button # * `description` (optional) A Markdown {String} containing a longer - # description about the notification. - # * `detail` (optional) A preformatted {String} that will be rendered as - # plain text with details about the notification. + # description about the notification. By default, this **will not** + # preserve newlines and whitespace when it is rendered. + # * `detail` (optional) A plain-text {String} containing additional details + # about the notification. By default, this **will** preserve newlines + # and whitespace when it is rendered. # * `dismissable` (optional) A {Boolean} indicating whether this # notification can be dismissed by the user. Defaults to `false`. # * `icon` (optional) A {String} name of an icon from Octicons to display From 7f61f4388e621a4e041e500911fb69723729ce14 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Mon, 4 Jul 2016 06:34:11 +0200 Subject: [PATCH 023/160] :arrow_up: image-view@0.58.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7aa699a51..3c7ccbd19 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "git-diff": "1.0.1", "go-to-line": "0.31.0", "grammar-selector": "0.48.1", - "image-view": "0.58.1", + "image-view": "0.58.2", "incompatible-packages": "0.26.1", "keybinding-resolver": "0.35.0", "line-ending-selector": "0.5.0", From 6f78d5c0f9dc1a2a24698840eff2a81b7d9e0669 Mon Sep 17 00:00:00 2001 From: Ammar Najjar Date: Mon, 4 Jul 2016 10:47:31 +0200 Subject: [PATCH 024/160] update nodejs installation instructions link for Fedora/Centos/RHEL --- docs/build-instructions/linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 126604c49..f737a6cda 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -25,7 +25,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. ### Fedora / CentOS / RHEL * `sudo dnf --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools` -* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#enterprise-linux-and-fedora). +* Instructions for [Node.js](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora). ### Arch From 4986a64815375e9abe1f080d3f96a6b290b3d222 Mon Sep 17 00:00:00 2001 From: Glavin Wiechert Date: Sat, 2 Jul 2016 16:26:36 -0300 Subject: [PATCH 025/160] Improve incompatible native module error message Close #6771 --- src/package.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/package.coffee b/src/package.coffee index 94e759947..4cb322691 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -426,8 +426,8 @@ class Package return @mainModule if @mainModuleRequired unless @isCompatible() console.warn """ - Failed to require the main module of '#{@name}' because it requires an incompatible native module. - Run `apm rebuild` in the package directory to resolve. + Failed to require the main module of '#{@name}' because it requires an incompatible native module (#{_.map(@incompatibleModules, 'name').join(', ')}). + Run `apm rebuild` in the package directory and restart Atom to resolve. """ return mainModulePath = @getMainModulePath() From c8263bddb99c1fca8146663945d40a81998f0035 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 5 Jul 2016 09:49:42 -0700 Subject: [PATCH 026/160] Use newer OS X on Travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 58f82c013..e894731ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,8 @@ env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 +osx_image: xcode7.3 + compiler: clang matrix: From 98fc8db3daa2021d391f03f93b1de8f40e424cb4 Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Tue, 5 Jul 2016 10:23:02 -0700 Subject: [PATCH 027/160] :arrow_up: find-and-replace@0.201.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c7ccbd19..29152f4ad 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "dev-live-reload": "0.47.0", "encoding-selector": "0.22.0", "exception-reporting": "0.38.1", - "find-and-replace": "0.200.0", + "find-and-replace": "0.201.0", "fuzzy-finder": "1.2.0", "git-diff": "1.0.1", "go-to-line": "0.31.0", From 9bf329cef250188c7917ce9d00ebf5bd9db7996f Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Thu, 7 Jul 2016 15:53:07 -0700 Subject: [PATCH 028/160] Tear down ipc response handler when atom environment is destroyed Signed-off-by: Nathan Sobo --- src/atom-environment.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 5247ceb97..327b9ea1a 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -224,11 +224,12 @@ class AtomEnvironment extends Model @observeAutoHideMenuBar() - checkPortableHomeWritable = -> + checkPortableHomeWritable = => responseChannel = "check-portable-home-writable-response" ipcRenderer.on responseChannel, (event, response) -> ipcRenderer.removeAllListeners(responseChannel) - atom.notifications.addWarning("#{response.message.replace(/([\\\.+\\-_#!])/g, '\\$1')}") if not response.writable + @notifications.addWarning("#{response.message.replace(/([\\\.+\\-_#!])/g, '\\$1')}") if not response.writable + @disposables.add new Disposable => ipcRenderer.removeAllListeners(responseChannel) ipcRenderer.send('check-portable-home-writable', responseChannel) checkPortableHomeWritable() From 3e826c1357808de0442a807149f0185a39c78d16 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Fri, 8 Jul 2016 10:04:59 -0700 Subject: [PATCH 029/160] Initial checkpoint not yet tested with settings-view changes --- src/main-process/squirrel-update.coffee | 8 +- src/main-process/win-registry.coffee | 62 ------------- src/main-process/win-shell.coffee | 115 ++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 66 deletions(-) delete mode 100644 src/main-process/win-registry.coffee create mode 100644 src/main-process/win-shell.coffee diff --git a/src/main-process/squirrel-update.coffee b/src/main-process/squirrel-update.coffee index a1bfc5359..167fe105a 100644 --- a/src/main-process/squirrel-update.coffee +++ b/src/main-process/squirrel-update.coffee @@ -1,7 +1,7 @@ fs = require 'fs-plus' path = require 'path' Spawner = require './spawner' -WinRegistry = require './win-registry' +WinShell = require './win-shell' WinPowerShell = require './win-powershell' appFolder = path.resolve(process.execPath, '..') @@ -130,19 +130,19 @@ exports.handleStartupEvent = (app, squirrelCommand) -> switch squirrelCommand when '--squirrel-install' createShortcuts -> - WinRegistry.installContextMenu -> + WindowsShell.installingAtom -> addCommandsToPath -> app.quit() true when '--squirrel-updated' updateShortcuts -> - WinRegistry.installContextMenu -> + WindowsShell.upgradingAtom -> addCommandsToPath -> app.quit() true when '--squirrel-uninstall' removeShortcuts -> - WinRegistry.uninstallContextMenu -> + WindowsShell.uninstallingAtom -> removeCommandsFromPath -> app.quit() true diff --git a/src/main-process/win-registry.coffee b/src/main-process/win-registry.coffee deleted file mode 100644 index f4b81b377..000000000 --- a/src/main-process/win-registry.coffee +++ /dev/null @@ -1,62 +0,0 @@ -path = require 'path' -Spawner = require './spawner' - -if process.env.SystemRoot - system32Path = path.join(process.env.SystemRoot, 'System32') - regPath = path.join(system32Path, 'reg.exe') -else - regPath = 'reg.exe' - -# Registry keys used for context menu -fileKeyPath = 'HKCU\\Software\\Classes\\*\\shell\\Atom' -directoryKeyPath = 'HKCU\\Software\\Classes\\directory\\shell\\Atom' -backgroundKeyPath = 'HKCU\\Software\\Classes\\directory\\background\\shell\\Atom' -applicationsKeyPath = 'HKCU\\Software\\Classes\\Applications\\atom.exe' - -# Spawn reg.exe and callback when it completes -spawnReg = (args, callback) -> - Spawner.spawn(regPath, args, callback) - -# Install the Open with Atom explorer context menu items via the registry. -# -# * `callback` The {Function} to call after registry operation is done. -# It will be invoked with the same arguments provided by {Spawner.spawn}. -# -# Returns `undefined`. -exports.installContextMenu = (callback) -> - addToRegistry = (args, callback) -> - args.unshift('add') - args.push('/f') - spawnReg(args, callback) - - installFileHandler = (callback) -> - args = ["#{applicationsKeyPath}\\shell\\open\\command", '/ve', '/d', "\"#{process.execPath}\" \"%1\""] - addToRegistry(args, callback) - - installMenu = (keyPath, arg, callback) -> - args = [keyPath, '/ve', '/d', 'Open with Atom'] - addToRegistry args, -> - args = [keyPath, '/v', 'Icon', '/d', "\"#{process.execPath}\""] - addToRegistry args, -> - args = ["#{keyPath}\\command", '/ve', '/d', "\"#{process.execPath}\" \"#{arg}\""] - addToRegistry(args, callback) - - installMenu fileKeyPath, '%1', -> - installMenu directoryKeyPath, '%1', -> - installMenu backgroundKeyPath, '%V', -> - installFileHandler(callback) - -# Uninstall the Open with Atom explorer context menu items via the registry. -# -# * `callback` The {Function} to call after registry operation is done. -# It will be invoked with the same arguments provided by {Spawner.spawn}. -# -# Returns `undefined`. -exports.uninstallContextMenu = (callback) -> - deleteFromRegistry = (keyPath, callback) -> - spawnReg(['delete', keyPath, '/f'], callback) - - deleteFromRegistry fileKeyPath, -> - deleteFromRegistry directoryKeyPath, -> - deleteFromRegistry backgroundKeyPath, -> - deleteFromRegistry(applicationsKeyPath, callback) diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee new file mode 100644 index 000000000..a3ce033c0 --- /dev/null +++ b/src/main-process/win-shell.coffee @@ -0,0 +1,115 @@ +Registry = require 'winreg' +Path = require 'path' + +exeName = Path.basename(process.execPath) +appPath = "\"#{process.execPath}\"" +appName = exeName.replace('atom', 'Atom').replace('beta', 'Beta').replace('.exe', '') + +contextRegistrationParts = [ + {key: 'command', name: '', value: "#{appPath} \"%1\""}, + {name: '', value: "Open with #{appName}"}, + {name: 'Icon', value: "#{appPath}"} +] + +# Register Atom as a file handler to be associated with file types +exports.isFileHandlerRegistered = (callback) -> + isRegisteredToThisApp fileHandlerRegistration, callback + +exports.registerFileHandler = (callback) -> + addToRegistry fileHandlerRegistration, callback + +exports.removeFileHandler = (callback) -> + removeFromRegistry fileHandlerRegistration, callback + +fileHandlerRegistration = { + key: "\\Software\\Classes\\Applications\\#{exeName}", + parts: [{key: 'shell\\open\\command', name: '', value: "#{appPath} \"%1\""}] +} + +# Add "Open with Atom" to the File Explorer context menu for files +exports.isInContextFilesMenu = (callback) -> + isRegisteredToThisApp contextFilesRegistration, callback + +exports.addToContextFilesMenu = (callback) -> + addToRegistry contextFilesRegistration, callback + +exports.removeFromContextFilesMenu = (callback) -> + removeFromRegistry contextFilesRegistration, callback + +contextFilesRegistration = { + key: "\\Software\\Classes\\*\\shell\\#{appName}", + parts: contextRegistryParts +} + +# Add "Open with Atom" to the File Explorer context menu for folders +exports.isInContextFoldersMenu = (callback) -> + isRegisteredToThisApp contextFoldersRegistration, callback + +exports.addToContextFoldersMenu = (callback) -> + addToRegistry contextFoldersRegistration, -> + addToRegistry contexBackgroundRegistration, callback + +exports.removeFromContextFoldersMenu = (callback) -> + removeFromRegistry contextFoldersRegistration, -> + removeFromRegistry contextBackgroundRegistration, callback + +contextFoldersRegistration = { + key: "\\Software\\Classes\\Directory\\shell\\#{appName}", # Right-click folder + parts: contextRegistryParts +} + +contextFoldersBackgroundRegistration = { # Right-click the background of a folder + key: "\\Software\\Classes\\Directory\\background\\shell\\#{appName}", + parts: JSON.parse(JSON.stringify(contextRegistryParts).replace('%1', '%V')) +} + +# Installing Atom should register the file handler only +exports.installingAtom = (callback) -> + registerFileHandler callback + +# Upgrading Atom should upgrade any existing registry keys for this exeName +exports.upgradingAtom = (callback) -> + updateRegistryIfSameExeName fileHandlerRegistration, -> + updateRegistryIfSameExeName contextFileRegistration, -> + updateRegistryIfSameExeName contextFolderRegistration, -> + updateRegistryIfSameExeName contextBackgroundRegistration, callback + +# Uninstalling Atom should remove any registry keys pointing to this appPath +exports.uninstallingAtom = (callback) -> + removeFromRegistryIfUs fileHandlerRegistration, -> + removeFromRegistryIfUs contextFileRegistration, -> + removeFromRegistryIfUs contextFolderRegistration, -> + removeFromRegistryIfUs contextBackgroundRegistration, callback + +getRegistryFirstValue = (registration, callback) -> + primaryPart = registration.parts[0] + new Registry({hive: 'HKCU', key: "#{registration.key}\\#{primaryPart.key}"}) + .get primaryPart.name, callback + +isRegisteredToThisApp = (registration, callback) -> + getRegistryFirstValue registration, (err, val) -> + callback(not err? and val.value is registration.parts[0].value) + +addToRegistry = (registration, callback) -> + doneCount = registration.parts.length + registration.parts.forEach((part) -> + reg = new Registry({hive: 'HKCU', key: if part.key? then "#{registration.key}\\#{part.key}" else registration.key}) + reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if doneCount-- is 0) + ) + +updateRegistryIfSameExeName = (registration, callback) -> + getRegistryFirstValue registration, (err, val) -> + if not err? and val.value.endsWith(exeName) + addToRegistry registration, callback + else + callback(err, val) + +removeFromRegistry = (registration, callback) -> + new Registry({hive: 'HKCU', key: registration.key}).destroy callback + +removeFromRegistryIfThisApp = (registration, callback) -> + isRegisteredToThisApp registration, (isThisApp) -> + if isThisApp + removeFromRegistry registration, callback + else + callback(isThisApp) From 6a4f6751d12f4a43db8b3dad4e60a54ae01af762 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Fri, 8 Jul 2016 13:31:19 -0700 Subject: [PATCH 030/160] Revise API to reduce surface area --- package.json | 1 + src/main-process/squirrel-update.coffee | 20 ++-- src/main-process/win-shell.coffee | 134 +++++++----------------- 3 files changed, 49 insertions(+), 106 deletions(-) diff --git a/package.json b/package.json index 29152f4ad..583699946 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "text-buffer": "9.2.2", "typescript-simple": "1.0.0", "underscore-plus": "^1.6.6", + "winreg": "^1.2.1", "yargs": "^3.23.0" }, "packageDependencies": { diff --git a/src/main-process/squirrel-update.coffee b/src/main-process/squirrel-update.coffee index 167fe105a..5dfff6710 100644 --- a/src/main-process/squirrel-update.coffee +++ b/src/main-process/squirrel-update.coffee @@ -130,21 +130,27 @@ exports.handleStartupEvent = (app, squirrelCommand) -> switch squirrelCommand when '--squirrel-install' createShortcuts -> - WindowsShell.installingAtom -> + WinShell.fileHandler.register -> addCommandsToPath -> app.quit() true when '--squirrel-updated' updateShortcuts -> - WindowsShell.upgradingAtom -> - addCommandsToPath -> - app.quit() + WinShell.fileHandler.update -> + WinShell.fileContextMenu.update -> + WinShell.folderContextMenu.update -> + WinShell.folderBackgroundContextMenu.update -> + addCommandsToPath -> + app.quit() true when '--squirrel-uninstall' removeShortcuts -> - WindowsShell.uninstallingAtom -> - removeCommandsFromPath -> - app.quit() + WinShell.fileHandler.deregister -> + WinShell.fileContextMenu.deregister -> + WinShell.folderContextMenu.deregister -> + WinShell.folderBackgroundContextMenu.deregister -> + removeCommandsFromPath -> + app.quit() true when '--squirrel-obsolete' app.quit() diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee index a3ce033c0..2cc3f066c 100644 --- a/src/main-process/win-shell.coffee +++ b/src/main-process/win-shell.coffee @@ -5,111 +5,47 @@ exeName = Path.basename(process.execPath) appPath = "\"#{process.execPath}\"" appName = exeName.replace('atom', 'Atom').replace('beta', 'Beta').replace('.exe', '') +class ShellOption + constructor: (key, parts) -> + @key = key + @parts = parts + isRegistered: (callback) => + new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) + .get @parts[0].name, (err, val) -> + callback(not err? and val.value is @parts[0].value) + register: (callback) -> + doneCount = @parts.length + @parts.forEach((part) -> + reg = new Registry({hive: 'HKCU', key: if @part.key? then "#{@key}\\#{@part.key}" else @key}) + reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if doneCount-- is 0)) + deregister: (callback) -> + @isRegistered (isRegistered) -> + if isRegistered + new Registry({hive: 'HKCU', key: @key}).destroy callback null, true + else + callback null, false + update: (callback) -> + new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) + .get @parts[0].name, (err, val) -> + if err? or not val.value.endsWith '\\' + exeName + callback err, val + else + register callback + +exports.fileHandler = new ShellOption("\\Software\\Classes\\Applications\\#{exeName}", + parts: [{key: 'shell\\open\\command', name: '', value: "#{appPath} \"%1\""}] +) + contextRegistrationParts = [ {key: 'command', name: '', value: "#{appPath} \"%1\""}, {name: '', value: "Open with #{appName}"}, {name: 'Icon', value: "#{appPath}"} ] -# Register Atom as a file handler to be associated with file types -exports.isFileHandlerRegistered = (callback) -> - isRegisteredToThisApp fileHandlerRegistration, callback +exports.fileContextMenu = new ShellOption("\\Software\\Classes\\*\\shell\\#{appName}", parts: contextRegistryParts) -exports.registerFileHandler = (callback) -> - addToRegistry fileHandlerRegistration, callback +exports.folderContextMenu = new ShellOption("\\Software\\Classes\\Directory\\shell\\#{appName}", parts: contextRegistryParts) -exports.removeFileHandler = (callback) -> - removeFromRegistry fileHandlerRegistration, callback - -fileHandlerRegistration = { - key: "\\Software\\Classes\\Applications\\#{exeName}", - parts: [{key: 'shell\\open\\command', name: '', value: "#{appPath} \"%1\""}] -} - -# Add "Open with Atom" to the File Explorer context menu for files -exports.isInContextFilesMenu = (callback) -> - isRegisteredToThisApp contextFilesRegistration, callback - -exports.addToContextFilesMenu = (callback) -> - addToRegistry contextFilesRegistration, callback - -exports.removeFromContextFilesMenu = (callback) -> - removeFromRegistry contextFilesRegistration, callback - -contextFilesRegistration = { - key: "\\Software\\Classes\\*\\shell\\#{appName}", - parts: contextRegistryParts -} - -# Add "Open with Atom" to the File Explorer context menu for folders -exports.isInContextFoldersMenu = (callback) -> - isRegisteredToThisApp contextFoldersRegistration, callback - -exports.addToContextFoldersMenu = (callback) -> - addToRegistry contextFoldersRegistration, -> - addToRegistry contexBackgroundRegistration, callback - -exports.removeFromContextFoldersMenu = (callback) -> - removeFromRegistry contextFoldersRegistration, -> - removeFromRegistry contextBackgroundRegistration, callback - -contextFoldersRegistration = { - key: "\\Software\\Classes\\Directory\\shell\\#{appName}", # Right-click folder - parts: contextRegistryParts -} - -contextFoldersBackgroundRegistration = { # Right-click the background of a folder - key: "\\Software\\Classes\\Directory\\background\\shell\\#{appName}", +exports.folderBackgroundContextMenu = new ShellOption("\\Software\\Classes\\Directory\\background\\shell\\#{appName}", parts: JSON.parse(JSON.stringify(contextRegistryParts).replace('%1', '%V')) -} - -# Installing Atom should register the file handler only -exports.installingAtom = (callback) -> - registerFileHandler callback - -# Upgrading Atom should upgrade any existing registry keys for this exeName -exports.upgradingAtom = (callback) -> - updateRegistryIfSameExeName fileHandlerRegistration, -> - updateRegistryIfSameExeName contextFileRegistration, -> - updateRegistryIfSameExeName contextFolderRegistration, -> - updateRegistryIfSameExeName contextBackgroundRegistration, callback - -# Uninstalling Atom should remove any registry keys pointing to this appPath -exports.uninstallingAtom = (callback) -> - removeFromRegistryIfUs fileHandlerRegistration, -> - removeFromRegistryIfUs contextFileRegistration, -> - removeFromRegistryIfUs contextFolderRegistration, -> - removeFromRegistryIfUs contextBackgroundRegistration, callback - -getRegistryFirstValue = (registration, callback) -> - primaryPart = registration.parts[0] - new Registry({hive: 'HKCU', key: "#{registration.key}\\#{primaryPart.key}"}) - .get primaryPart.name, callback - -isRegisteredToThisApp = (registration, callback) -> - getRegistryFirstValue registration, (err, val) -> - callback(not err? and val.value is registration.parts[0].value) - -addToRegistry = (registration, callback) -> - doneCount = registration.parts.length - registration.parts.forEach((part) -> - reg = new Registry({hive: 'HKCU', key: if part.key? then "#{registration.key}\\#{part.key}" else registration.key}) - reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if doneCount-- is 0) - ) - -updateRegistryIfSameExeName = (registration, callback) -> - getRegistryFirstValue registration, (err, val) -> - if not err? and val.value.endsWith(exeName) - addToRegistry registration, callback - else - callback(err, val) - -removeFromRegistry = (registration, callback) -> - new Registry({hive: 'HKCU', key: registration.key}).destroy callback - -removeFromRegistryIfThisApp = (registration, callback) -> - isRegisteredToThisApp registration, (isThisApp) -> - if isThisApp - removeFromRegistry registration, callback - else - callback(isThisApp) +) From d343592fedf5f18e2ff0e23560c6c159ba5e09a3 Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 9 Jul 2016 16:40:59 +0900 Subject: [PATCH 031/160] :arrow_up: atom-ui@0.4.0 New inputs: https://github.com/atom/atom-ui/pull/8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29152f4ad..4ae67fcb7 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dependencies": { "async": "0.2.6", "atom-keymap": "6.3.2", - "atom-ui": "0.3.3", + "atom-ui": "0.4.0", "babel-core": "^5.8.21", "cached-run-in-this-context": "0.4.1", "chai": "3.5.0", From 57faec33bb6730a27b06d1bfe9ce32bfd76f3bfa Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 9 Jul 2016 17:06:41 +0900 Subject: [PATCH 032/160] :arrow_up: styleguide@v0.47.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4ae67fcb7..702b7b9a0 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "snippets": "1.0.2", "spell-check": "0.67.1", "status-bar": "1.3.1", - "styleguide": "0.46.0", + "styleguide": "0.47.0", "symbols-view": "0.113.0", "tabs": "0.99.0", "timecop": "0.33.1", From 81ebb686bb7aa9e8a040cac18877b0e3d0c4766f Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Mon, 11 Jul 2016 09:59:08 -0700 Subject: [PATCH 033/160] Fixes from testing Windows shell integration --- exports/atom.coffee | 4 ++++ src/main-process/win-shell.coffee | 28 +++++++++++++++------------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/exports/atom.coffee b/exports/atom.coffee index 4953d3756..a76352164 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -19,6 +19,10 @@ module.exports = Disposable: Disposable CompositeDisposable: CompositeDisposable +# Shell integration is required by both Squirrel and Settings-View +if process.platform is 'win32' + module.exports.WinShell = require '../src/main-process/win-shell' + # The following classes can't be used from a Task handler and should therefore # only be exported when not running as a child node process unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee index 2cc3f066c..5e1e1428a 100644 --- a/src/main-process/win-shell.coffee +++ b/src/main-process/win-shell.coffee @@ -11,20 +11,20 @@ class ShellOption @parts = parts isRegistered: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) - .get @parts[0].name, (err, val) -> + .get @parts[0].name, (err, val) => callback(not err? and val.value is @parts[0].value) - register: (callback) -> + register: (callback) => doneCount = @parts.length - @parts.forEach((part) -> - reg = new Registry({hive: 'HKCU', key: if @part.key? then "#{@key}\\#{@part.key}" else @key}) + @parts.forEach((part) => + reg = new Registry({hive: 'HKCU', key: if part.key? then "#{@key}\\#{part.key}" else @key}) reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if doneCount-- is 0)) - deregister: (callback) -> - @isRegistered (isRegistered) -> + deregister: (callback) => + @isRegistered (isRegistered) => if isRegistered - new Registry({hive: 'HKCU', key: @key}).destroy callback null, true + new Registry({hive: 'HKCU', key: @key}).destroy -> callback null, true else callback null, false - update: (callback) -> + update: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) .get @parts[0].name, (err, val) -> if err? or not val.value.endsWith '\\' + exeName @@ -32,20 +32,22 @@ class ShellOption else register callback +exports.appName = appName + exports.fileHandler = new ShellOption("\\Software\\Classes\\Applications\\#{exeName}", - parts: [{key: 'shell\\open\\command', name: '', value: "#{appPath} \"%1\""}] + [{key: 'shell\\open\\command', name: '', value: "#{appPath} \"%1\""}] ) -contextRegistrationParts = [ +contextParts = [ {key: 'command', name: '', value: "#{appPath} \"%1\""}, {name: '', value: "Open with #{appName}"}, {name: 'Icon', value: "#{appPath}"} ] -exports.fileContextMenu = new ShellOption("\\Software\\Classes\\*\\shell\\#{appName}", parts: contextRegistryParts) +exports.fileContextMenu = new ShellOption("\\Software\\Classes\\*\\shell\\#{appName}", contextParts) -exports.folderContextMenu = new ShellOption("\\Software\\Classes\\Directory\\shell\\#{appName}", parts: contextRegistryParts) +exports.folderContextMenu = new ShellOption("\\Software\\Classes\\Directory\\shell\\#{appName}", contextParts) exports.folderBackgroundContextMenu = new ShellOption("\\Software\\Classes\\Directory\\background\\shell\\#{appName}", - parts: JSON.parse(JSON.stringify(contextRegistryParts).replace('%1', '%V')) + JSON.parse(JSON.stringify(contextParts).replace('%1', '%V')) ) From 2f58792577e5a3d9a9551870fd6da1c3118b8596 Mon Sep 17 00:00:00 2001 From: simurai Date: Tue, 12 Jul 2016 15:36:50 +0900 Subject: [PATCH 034/160] Introduce @use-custom-controls variable --- static/variables/ui-variables.less | 1 + 1 file changed, 1 insertion(+) diff --git a/static/variables/ui-variables.less b/static/variables/ui-variables.less index 0a549954d..dd0561932 100644 --- a/static/variables/ui-variables.less +++ b/static/variables/ui-variables.less @@ -83,3 +83,4 @@ // Other @font-family: 'BlinkMacSystemFont', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif; +@use-custom-controls: true; // false uses native controls From 14bcc5f7f2a190b58ecf2e67ed302f1cc52b22c2 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Tue, 12 Jul 2016 13:59:48 +0200 Subject: [PATCH 035/160] :arrow_up: tree-view@0.208.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 702b7b9a0..e27bc3cd1 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "symbols-view": "0.113.0", "tabs": "0.99.0", "timecop": "0.33.1", - "tree-view": "0.208.0", + "tree-view": "0.208.1", "update-package-dependencies": "0.10.0", "welcome": "0.34.0", "whitespace": "0.32.2", From ce6d45f72a976ea55dc9a0ac5c4de3fde76c46f9 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Tue, 12 Jul 2016 10:03:55 -0700 Subject: [PATCH 036/160] :art: Fix fat-arrow linter warning --- src/atom-environment.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 327b9ea1a..7c81eaeee 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -229,7 +229,7 @@ class AtomEnvironment extends Model ipcRenderer.on responseChannel, (event, response) -> ipcRenderer.removeAllListeners(responseChannel) @notifications.addWarning("#{response.message.replace(/([\\\.+\\-_#!])/g, '\\$1')}") if not response.writable - @disposables.add new Disposable => ipcRenderer.removeAllListeners(responseChannel) + @disposables.add new Disposable -> ipcRenderer.removeAllListeners(responseChannel) ipcRenderer.send('check-portable-home-writable', responseChannel) checkPortableHomeWritable() From 9f6f9035927e80a4315d470d965ea823b2c78b7d Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Tue, 12 Jul 2016 15:31:49 -0700 Subject: [PATCH 037/160] Add enhanced wording @thomasjo recommended --- src/package.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.coffee b/src/package.coffee index 4cb322691..b27e3ce0e 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -426,7 +426,7 @@ class Package return @mainModule if @mainModuleRequired unless @isCompatible() console.warn """ - Failed to require the main module of '#{@name}' because it requires an incompatible native module (#{_.map(@incompatibleModules, 'name').join(', ')}). + Failed to require the main module of '#{@name}' because it requires one or more incompatible native modules (#{_.map(@incompatibleModules, 'name').join(', ')}). Run `apm rebuild` in the package directory and restart Atom to resolve. """ return From 5a8ced324e4885b5f49a554d0da3d00f8b49dc95 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Tue, 12 Jul 2016 18:11:59 -0700 Subject: [PATCH 038/160] Fixup Squirrel installer spec tests --- spec/squirrel-update-spec.coffee | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/spec/squirrel-update-spec.coffee b/spec/squirrel-update-spec.coffee index a8a39eb54..51442abc6 100644 --- a/spec/squirrel-update-spec.coffee +++ b/spec/squirrel-update-spec.coffee @@ -5,7 +5,7 @@ temp = require 'temp' SquirrelUpdate = require '../src/main-process/squirrel-update' Spawner = require '../src/main-process/spawner' WinPowerShell = require '../src/main-process/win-powershell' -WinRegistry = require '../src/main-process/win-registry' +WinShell = require '../src/main-process/win-shell' # Run passed callback as Spawner.spawn() would do invokeCallback = (callback) -> @@ -26,12 +26,11 @@ describe "Windows Squirrel Update", -> # do nothing on command, just run passed callback invokeCallback callback - # Prevent any actual change to Windows registry - for own method of WinRegistry - # all WinRegistry APIs share the same signature - spyOn(WinRegistry, method).andCallFake (callback) -> - # do nothing on registry, just run passed callback - invokeCallback callback + # Prevent any actual change to Windows Shell + for own property of WinShell + for own method of property + spyOn(property, method).andCallFake (callback) -> + invokeCallback callback it "quits the app on all squirrel events", -> app = quit: jasmine.createSpy('quit') From cb023016ccfb4ac8a3b5b419f3ba55a7047f9a45 Mon Sep 17 00:00:00 2001 From: simurai Date: Wed, 13 Jul 2016 12:23:47 +0900 Subject: [PATCH 039/160] :arrow_up: atom-ui@0.4.1 Allow themes to opt-out of custom control styling --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e27bc3cd1..e20cac067 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dependencies": { "async": "0.2.6", "atom-keymap": "6.3.2", - "atom-ui": "0.4.0", + "atom-ui": "0.4.1", "babel-core": "^5.8.21", "cached-run-in-this-context": "0.4.1", "chai": "3.5.0", From a4b9e94d7bf69e3f43968b48a556c8a21fc49899 Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Wed, 13 Jul 2016 08:56:42 -0700 Subject: [PATCH 040/160] :arrow_up: settings-view@0.240.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e20cac067..4cbdd1ff9 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "notifications": "0.65.0", "open-on-github": "1.1.0", "package-generator": "1.0.0", - "settings-view": "0.240.0", + "settings-view": "0.240.1", "snippets": "1.0.2", "spell-check": "0.67.1", "status-bar": "1.3.1", From 7b11c31e07af37cdbdf5d9c9b9d30aec6a4b09f5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Jul 2016 14:02:05 -0700 Subject: [PATCH 041/160] Remove synchronous GitRepository's dependency on GitRepositoryAsync Signed-off-by: Nathan Sobo --- spec/git-repository-async-spec.js | 2 +- spec/git-spec.coffee | 30 ---------- src/git-repository-provider.coffee | 2 +- src/git-repository.coffee | 83 ++++++++-------------------- src/repository-status-handler.coffee | 19 ++++++- 5 files changed, 43 insertions(+), 93 deletions(-) diff --git a/spec/git-repository-async-spec.js b/spec/git-repository-async-spec.js index 8b824bab3..4165e258e 100644 --- a/spec/git-repository-async-spec.js +++ b/spec/git-repository-async-spec.js @@ -33,7 +33,7 @@ function copySubmoduleRepository () { return workingDirectory } -describe('GitRepositoryAsync', () => { +fdescribe('GitRepositoryAsync', () => { let repo afterEach(() => { diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index a9de506a2..21624c452 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -259,36 +259,6 @@ describe "GitRepository", -> expect(repo.isStatusModified(status)).toBe false expect(repo.isStatusNew(status)).toBe false - it 'caches the proper statuses when multiple project are open', -> - otherWorkingDirectory = copyRepository() - - atom.project.setPaths([workingDirectory, otherWorkingDirectory]) - - waitsForPromise -> - atom.workspace.open('b.txt') - - statusHandler = null - runs -> - repo = atom.project.getRepositories()[0] - - statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatuses statusHandler - repo.refreshStatus() - - waitsFor -> - statusHandler.callCount > 0 - - runs -> - subDir = path.join(workingDirectory, 'dir') - fs.mkdirSync(subDir) - - filePath = path.join(subDir, 'b.txt') - fs.writeFileSync(filePath, '') - - status = repo.getCachedPathStatus(filePath) - expect(repo.isStatusModified(status)).toBe true - expect(repo.isStatusNew(status)).toBe false - it 'caches statuses that were looked up synchronously', -> originalContent = 'undefined' fs.writeFileSync(modifiedPath, 'making this path modified') diff --git a/src/git-repository-provider.coffee b/src/git-repository-provider.coffee index 463e2bda2..593324d0c 100644 --- a/src/git-repository-provider.coffee +++ b/src/git-repository-provider.coffee @@ -77,7 +77,7 @@ class GitRepositoryProvider unless repo repo = GitRepository.open(gitDirPath, {@project, @config}) return null unless repo - repo.async.onDidDestroy(=> delete @pathToRepository[gitDirPath]) + repo.onDidDestroy(=> delete @pathToRepository[gitDirPath]) @pathToRepository[gitDirPath] = repo repo.refreshIndex() repo.refreshStatus() diff --git a/src/git-repository.coffee b/src/git-repository.coffee index f6bacb760..6f0851cf9 100644 --- a/src/git-repository.coffee +++ b/src/git-repository.coffee @@ -83,12 +83,11 @@ class GitRepository asyncOptions.subscribeToBuffers = false @async = GitRepositoryAsync.open(path, asyncOptions) + @statuses = {} @upstream = {ahead: 0, behind: 0} for submodulePath, submoduleRepo of @repo.submodules submoduleRepo.upstream = {ahead: 0, behind: 0} - @statusesByPath = {} - {@project, @config, refreshOnWindowFocus} = options refreshOnWindowFocus ?= true @@ -126,14 +125,6 @@ class GitRepository @subscriptions.dispose() @subscriptions = null - if @async? - @async.destroy() - @async = null - - # Public: Returns a {Boolean} indicating if this repository has been destroyed. - isDestroyed: -> - not @repo? - # Public: Invoke the given callback when this GitRepository's destroy() method # is invoked. # @@ -322,7 +313,7 @@ class GitRepository getDirectoryStatus: (directoryPath) -> directoryPath = "#{@relativize(directoryPath)}/" directoryStatus = 0 - for path, status of Object.assign({}, @async.getCachedPathStatuses(), @statusesByPath) + for path, status of @statuses directoryStatus |= status if path.indexOf(directoryPath) is 0 directoryStatus @@ -335,24 +326,13 @@ class GitRepository getPathStatus: (path) -> repo = @getRepo(path) relativePath = @relativize(path) - - # This is a bit particular. If a package calls `getPathStatus` like this: - # - change the file - # - getPathStatus - # - change the file - # - getPathStatus - # We need to preserve the guarantee that each call to `getPathStatus` will - # synchronously emit 'did-change-status'. So we need to keep a cache of the - # statuses found from this call. - currentPathStatus = @getCachedRelativePathStatus(relativePath) ? 0 - - # Trigger events emitted on the async repo as well - @async.refreshStatusForPath(path) - + currentPathStatus = @statuses[relativePath] ? 0 pathStatus = repo.getStatus(repo.relativize(path)) ? 0 pathStatus = 0 if repo.isStatusIgnored(pathStatus) - @statusesByPath[relativePath] = pathStatus - + if pathStatus > 0 + @statuses[relativePath] = pathStatus + else + delete @statuses[relativePath] if currentPathStatus isnt pathStatus @emitter.emit 'did-change-status', {path, pathStatus} @@ -364,11 +344,7 @@ class GitRepository # # Returns a status {Number} or null if the path is not in the cache. getCachedPathStatus: (path) -> - relativePath = @relativize(path) - @getCachedRelativePathStatus(relativePath) - - getCachedRelativePathStatus: (relativePath) -> - @statusesByPath[relativePath] ? @async.getCachedPathStatuses()[relativePath] + @statuses[@relativize(path)] # Public: Returns true if the given status indicates modification. # @@ -492,42 +468,29 @@ class GitRepository # Refreshes the current git status in an outside process and asynchronously # updates the relevant properties. - # - # Returns a promise that resolves when the repository has been refreshed. refreshStatus: -> - statusesChanged = false + @handlerPath ?= require.resolve('./repository-status-handler') - # Listen for `did-change-statuses` so we know if something changed. But we - # need to wait to propagate it until after we've set the branch and cleared - # the `statusesByPath` cache. So just set a flag, and we'll emit the event - # after refresh is done. - subscription = @async.onDidChangeStatuses -> - subscription?.dispose() - subscription = null + relativeProjectPaths = @project?.getPaths() + .map (path) => @relativize(path) + .filter (path) -> path.length > 0 - statusesChanged = true + @statusTask?.terminate() + new Promise (resolve) => + @statusTask = Task.once @handlerPath, @getPath(), relativeProjectPaths, ({statuses, upstream, branch, submodules}) => + statusesUnchanged = _.isEqual(statuses, @statuses) and + _.isEqual(upstream, @upstream) and + _.isEqual(branch, @branch) and + _.isEqual(submodules, @submodules) - asyncRefresh = @async.refreshStatus().then => - subscription?.dispose() - subscription = null - - @branch = @async?.branch - @statusesByPath = {} - - if statusesChanged - @emitter.emit 'did-change-statuses' - - syncRefresh = new Promise (resolve, reject) => - @handlerPath ?= require.resolve('./repository-status-handler') - - @statusTask?.terminate() - @statusTask = Task.once @handlerPath, @getPath(), ({upstream, submodules}) => + @statuses = statuses @upstream = upstream + @branch = branch @submodules = submodules for submodulePath, submoduleRepo of @getRepo().submodules submoduleRepo.upstream = submodules[submodulePath]?.upstream ? {ahead: 0, behind: 0} + unless statusesUnchanged + @emitter.emit 'did-change-statuses' resolve() - - return Promise.all([asyncRefresh, syncRefresh]) diff --git a/src/repository-status-handler.coffee b/src/repository-status-handler.coffee index adae7bc4f..2fda9a335 100644 --- a/src/repository-status-handler.coffee +++ b/src/repository-status-handler.coffee @@ -5,15 +5,32 @@ module.exports = (repoPath, paths = []) -> repo = Git.open(repoPath) upstream = {} + statuses = {} submodules = {} + branch = null if repo? + # Statuses in main repo + workingDirectoryPath = repo.getWorkingDirectory() + repoStatus = (if paths.length > 0 then repo.getStatusForPaths(paths) else repo.getStatus()) + for filePath, status of repoStatus + statuses[filePath] = status + + # Statuses in submodules for submodulePath, submoduleRepo of repo.submodules submodules[submodulePath] = branch: submoduleRepo.getHead() upstream: submoduleRepo.getAheadBehindCount() + workingDirectoryPath = submoduleRepo.getWorkingDirectory() + for filePath, status of submoduleRepo.getStatus() + absolutePath = path.join(workingDirectoryPath, filePath) + # Make path relative to parent repository + relativePath = repo.relativize(absolutePath) + statuses[relativePath] = status + upstream = repo.getAheadBehindCount() + branch = repo.getHead() repo.release() - {upstream, submodules} + {statuses, upstream, branch, submodules} From 58e789249297adb99350fad38ed10d2513a47c23 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Jul 2016 14:03:29 -0700 Subject: [PATCH 042/160] Remove GitRepositoryAsync Signed-off-by: Nathan Sobo --- exports/atom.coffee | 1 - package.json | 1 - spec/git-repository-async-spec.js | 918 ------------------------------ spec/git-spec.coffee | 10 - src/git-repository-async.js | 558 ------------------ src/git-repository.coffee | 8 - 6 files changed, 1496 deletions(-) delete mode 100644 spec/git-repository-async-spec.js delete mode 100644 src/git-repository-async.js diff --git a/exports/atom.coffee b/exports/atom.coffee index 4953d3756..81d1726b8 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -8,7 +8,6 @@ module.exports = BufferedNodeProcess: require '../src/buffered-node-process' BufferedProcess: require '../src/buffered-process' GitRepository: require '../src/git-repository' - GitRepositoryAsync: require '../src/git-repository-async' Notification: require '../src/notification' TextBuffer: TextBuffer Point: Point diff --git a/package.json b/package.json index 4cbdd1ff9..186c22ecc 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "mocha": "2.5.1", "normalize-package-data": "^2.0.0", "nslog": "^3", - "ohnogit": "0.0.13", "oniguruma": "^5", "pathwatcher": "~6.5", "property-accessors": "^1.1.3", diff --git a/spec/git-repository-async-spec.js b/spec/git-repository-async-spec.js deleted file mode 100644 index 4165e258e..000000000 --- a/spec/git-repository-async-spec.js +++ /dev/null @@ -1,918 +0,0 @@ -'use babel' - -import fs from 'fs-plus' -import path from 'path' -import temp from 'temp' - -import {it, beforeEach, afterEach} from './async-spec-helpers' - -import GitRepositoryAsync from '../src/git-repository-async' -import Project from '../src/project' - -temp.track() - -function openFixture (fixture) { - return GitRepositoryAsync.open(path.join(__dirname, 'fixtures', 'git', fixture)) -} - -function copyRepository (name = 'working-dir') { - const workingDirPath = temp.mkdirSync('atom-working-dir') - fs.copySync(path.join(__dirname, 'fixtures', 'git', name), workingDirPath) - fs.renameSync(path.join(workingDirPath, 'git.git'), path.join(workingDirPath, '.git')) - return fs.realpathSync(workingDirPath) -} - -function copySubmoduleRepository () { - const workingDirectory = copyRepository('repo-with-submodules') - const reGit = (name) => { - fs.renameSync(path.join(workingDirectory, name, 'git.git'), path.join(workingDirectory, name, '.git')) - } - reGit('jstips') - reGit('You-Dont-Need-jQuery') - - return workingDirectory -} - -fdescribe('GitRepositoryAsync', () => { - let repo - - afterEach(() => { - if (repo != null) repo.destroy() - }) - - describe('@open(path)', () => { - it('should throw when no repository is found', async () => { - repo = GitRepositoryAsync.open(path.join(temp.dir, 'nogit.txt')) - - let threw = false - try { - await repo.getRepo() - } catch (e) { - threw = true - } - - expect(threw).toBe(true) - }) - }) - - describe('openedPath', () => { - it('is the path passed to .open', () => { - const workingDirPath = copyRepository() - repo = GitRepositoryAsync.open(workingDirPath) - expect(repo.openedPath).toBe(workingDirPath) - }) - }) - - describe('.getRepo()', () => { - beforeEach(() => { - const workingDirectory = copySubmoduleRepository() - repo = GitRepositoryAsync.open(workingDirectory) - waitsForPromise(() => repo.refreshStatus()) - }) - - it('returns the repository when not given a path', async () => { - const nodeGitRepo1 = await repo.getRepo() - const nodeGitRepo2 = await repo.getRepo() - expect(nodeGitRepo1.workdir()).toBe(nodeGitRepo2.workdir()) - }) - - it('returns the repository when given a non-submodule path', async () => { - const nodeGitRepo1 = await repo.getRepo() - const nodeGitRepo2 = await repo.getRepo('README') - expect(nodeGitRepo1.workdir()).toBe(nodeGitRepo2.workdir()) - }) - - it('returns the submodule repository when given a submodule path', async () => { - const nodeGitRepo1 = await repo.getRepo() - const nodeGitRepo2 = await repo.getRepo('jstips') - expect(nodeGitRepo1.workdir()).not.toBe(nodeGitRepo2.workdir()) - - const nodeGitRepo3 = await repo.getRepo('jstips/README.md') - expect(nodeGitRepo1.workdir()).not.toBe(nodeGitRepo3.workdir()) - expect(nodeGitRepo2.workdir()).toBe(nodeGitRepo3.workdir()) - }) - }) - - describe('.openRepository()', () => { - it('returns a new repository instance', async () => { - repo = openFixture('master.git') - - const originalRepo = await repo.getRepo() - expect(originalRepo).not.toBeNull() - - const nodeGitRepo = repo.openRepository() - expect(nodeGitRepo).not.toBeNull() - expect(originalRepo).not.toBe(nodeGitRepo) - }) - }) - - describe('.getPath()', () => { - it('returns the repository path for a repository path', async () => { - repo = openFixture('master.git') - const repoPath = await repo.getPath() - expect(repoPath).toEqualPath(path.join(__dirname, 'fixtures', 'git', 'master.git')) - }) - }) - - describe('.isPathIgnored(path)', () => { - beforeEach(() => { - repo = openFixture('ignore.git') - }) - - it('resolves true for an ignored path', async () => { - const ignored = await repo.isPathIgnored('a.txt') - expect(ignored).toBe(true) - }) - - it('resolves false for a non-ignored path', async () => { - const ignored = await repo.isPathIgnored('b.txt') - expect(ignored).toBe(false) - }) - }) - - describe('.isPathModified(path)', () => { - let filePath, newPath, emptyPath - - beforeEach(() => { - const workingDirPath = copyRepository() - repo = GitRepositoryAsync.open(workingDirPath) - filePath = path.join(workingDirPath, 'a.txt') - newPath = path.join(workingDirPath, 'new-path.txt') - fs.writeFileSync(newPath, "i'm new here") - emptyPath = path.join(workingDirPath, 'empty-path.txt') - }) - - describe('when the path is unstaged', () => { - it('resolves false if the path has not been modified', async () => { - const modified = await repo.isPathModified(filePath) - expect(modified).toBe(false) - }) - - it('resolves true if the path is modified', async () => { - fs.writeFileSync(filePath, 'change') - const modified = await repo.isPathModified(filePath) - expect(modified).toBe(true) - }) - - it('resolves false if the path is new', async () => { - const modified = await repo.isPathModified(newPath) - expect(modified).toBe(false) - }) - - it('resolves false if the path is invalid', async () => { - const modified = await repo.isPathModified(emptyPath) - expect(modified).toBe(false) - }) - }) - }) - - describe('.isPathNew(path)', () => { - let newPath - - beforeEach(() => { - const workingDirPath = copyRepository() - repo = GitRepositoryAsync.open(workingDirPath) - newPath = path.join(workingDirPath, 'new-path.txt') - fs.writeFileSync(newPath, "i'm new here") - }) - - describe('when the path is unstaged', () => { - it('returns true if the path is new', async () => { - const isNew = await repo.isPathNew(newPath) - expect(isNew).toBe(true) - }) - - it("returns false if the path isn't new", async () => { - const modified = await repo.isPathModified(newPath) - expect(modified).toBe(false) - }) - }) - }) - - describe('.checkoutHead(path)', () => { - let filePath - - beforeEach(() => { - const workingDirPath = copyRepository() - repo = GitRepositoryAsync.open(workingDirPath) - filePath = path.join(workingDirPath, 'a.txt') - }) - - it('no longer reports a path as modified after checkout', async () => { - let modified = await repo.isPathModified(filePath) - expect(modified).toBe(false) - - fs.writeFileSync(filePath, 'ch ch changes') - - modified = await repo.isPathModified(filePath) - expect(modified).toBe(true) - - await repo.checkoutHead(filePath) - - modified = await repo.isPathModified(filePath) - expect(modified).toBe(false) - }) - - it('restores the contents of the path to the original text', async () => { - fs.writeFileSync(filePath, 'ch ch changes') - await repo.checkoutHead(filePath) - expect(fs.readFileSync(filePath, 'utf8')).toBe('') - }) - - it('fires a did-change-status event if the checkout completes successfully', async () => { - fs.writeFileSync(filePath, 'ch ch changes') - - await repo.getPathStatus(filePath) - - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatus(statusHandler) - - await repo.checkoutHead(filePath) - - expect(statusHandler.callCount).toBe(1) - expect(statusHandler.argsForCall[0][0]).toEqual({path: filePath, pathStatus: 0}) - - await repo.checkoutHead(filePath) - expect(statusHandler.callCount).toBe(1) - }) - }) - - describe('.checkoutHeadForEditor(editor)', () => { - let filePath - let editor - - beforeEach(async () => { - spyOn(atom, 'confirm') - - const workingDirPath = copyRepository() - repo = new GitRepositoryAsync(workingDirPath, {project: atom.project, config: atom.config, confirm: atom.confirm}) - filePath = path.join(workingDirPath, 'a.txt') - fs.writeFileSync(filePath, 'ch ch changes') - - editor = await atom.workspace.open(filePath) - }) - - it('displays a confirmation dialog by default', async () => { - atom.confirm.andCallFake(({buttons}) => buttons.OK()) - atom.config.set('editor.confirmCheckoutHeadRevision', true) - - await repo.checkoutHeadForEditor(editor) - - expect(fs.readFileSync(filePath, 'utf8')).toBe('') - }) - - it('does not display a dialog when confirmation is disabled', async () => { - atom.config.set('editor.confirmCheckoutHeadRevision', false) - - await repo.checkoutHeadForEditor(editor) - - expect(fs.readFileSync(filePath, 'utf8')).toBe('') - expect(atom.confirm).not.toHaveBeenCalled() - }) - }) - - describe('.destroy()', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('throws an exception when any method is called after it is called', async () => { - repo.destroy() - - let error = null - try { - await repo.getShortHead() - } catch (e) { - error = e - } - - expect(error.name).toBe(GitRepositoryAsync.DestroyedErrorName) - - repo = null - }) - }) - - describe('.getPathStatus(path)', () => { - let filePath - - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - filePath = path.join(workingDirectory, 'file.txt') - }) - - it('trigger a status-changed event when the new status differs from the last cached one', async () => { - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatus(statusHandler) - fs.writeFileSync(filePath, '') - - await repo.getPathStatus(filePath) - - expect(statusHandler.callCount).toBe(1) - const status = GitRepositoryAsync.Git.Status.STATUS.WT_MODIFIED - expect(statusHandler.argsForCall[0][0]).toEqual({path: filePath, pathStatus: status}) - fs.writeFileSync(filePath, 'abc') - - await repo.getPathStatus(filePath) - expect(statusHandler.callCount).toBe(1) - }) - }) - - describe('.getDirectoryStatus(path)', () => { - let directoryPath, filePath - - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - directoryPath = path.join(workingDirectory, 'dir') - filePath = path.join(directoryPath, 'b.txt') - }) - - it('gets the status based on the files inside the directory', async () => { - await repo.checkoutHead(filePath) - - let result = await repo.getDirectoryStatus(directoryPath) - expect(repo.isStatusModified(result)).toBe(false) - - fs.writeFileSync(filePath, 'abc') - - result = await repo.getDirectoryStatus(directoryPath) - expect(repo.isStatusModified(result)).toBe(true) - }) - }) - - describe('.refreshStatus()', () => { - let newPath, modifiedPath, cleanPath, workingDirectory - - beforeEach(() => { - workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - modifiedPath = path.join(workingDirectory, 'file.txt') - newPath = path.join(workingDirectory, 'untracked.txt') - cleanPath = path.join(workingDirectory, 'other.txt') - fs.writeFileSync(cleanPath, 'Full of text') - fs.writeFileSync(newPath, '') - fs.writeFileSync(modifiedPath, 'making this path modified') - newPath = fs.absolute(newPath) // specs could be running under symbol path. - }) - - it('returns status information for all new and modified files', async () => { - await repo.refreshStatus() - - expect(await repo.getCachedPathStatus(cleanPath)).toBeUndefined() - expect(repo.isStatusNew(await repo.getCachedPathStatus(newPath))).toBe(true) - expect(repo.isStatusModified(await repo.getCachedPathStatus(modifiedPath))).toBe(true) - }) - - describe('in a repository with submodules', () => { - beforeEach(() => { - workingDirectory = copySubmoduleRepository() - repo = GitRepositoryAsync.open(workingDirectory) - modifiedPath = path.join(workingDirectory, 'jstips', 'README.md') - newPath = path.join(workingDirectory, 'You-Dont-Need-jQuery', 'untracked.txt') - cleanPath = path.join(workingDirectory, 'jstips', 'CONTRIBUTING.md') - fs.writeFileSync(newPath, '') - fs.writeFileSync(modifiedPath, 'making this path modified') - newPath = fs.absolute(newPath) // specs could be running under symbol path. - }) - - it('returns status information for all new and modified files', async () => { - await repo.refreshStatus() - - expect(await repo.getCachedPathStatus(cleanPath)).toBeUndefined() - expect(repo.isStatusNew(await repo.getCachedPathStatus(newPath))).toBe(true) - expect(repo.isStatusModified(await repo.getCachedPathStatus(modifiedPath))).toBe(true) - }) - }) - - it('caches the proper statuses when a subdir is open', async () => { - const subDir = path.join(workingDirectory, 'dir') - fs.mkdirSync(subDir) - - const filePath = path.join(subDir, 'b.txt') - fs.writeFileSync(filePath, '') - - atom.project.setPaths([subDir]) - - await atom.workspace.open('b.txt') - - const repo = atom.project.getRepositories()[0].async - - await repo.refreshStatus() - - const status = await repo.getCachedPathStatus(filePath) - expect(repo.isStatusModified(status)).toBe(false) - expect(repo.isStatusNew(status)).toBe(false) - }) - - it('caches the proper statuses when multiple project are open', async () => { - const otherWorkingDirectory = copyRepository() - - atom.project.setPaths([workingDirectory, otherWorkingDirectory]) - - await atom.workspace.open('b.txt') - - const repo = atom.project.getRepositories()[0].async - - await repo.refreshStatus() - - const subDir = path.join(workingDirectory, 'dir') - fs.mkdirSync(subDir) - - const filePath = path.join(subDir, 'b.txt') - fs.writeFileSync(filePath, 'some content!') - - const status = await repo.getCachedPathStatus(filePath) - expect(repo.isStatusModified(status)).toBe(true) - expect(repo.isStatusNew(status)).toBe(false) - }) - - it('emits did-change-statuses if the status changes', async () => { - const someNewPath = path.join(workingDirectory, 'MyNewJSFramework.md') - fs.writeFileSync(someNewPath, '') - - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatuses(statusHandler) - - await repo.refreshStatus() - - waitsFor('the onDidChangeStatuses handler to be called', () => statusHandler.callCount > 0) - }) - - it('emits did-change-statuses if the branch changes', async () => { - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatuses(statusHandler) - - repo._refreshBranch = jasmine.createSpy('_refreshBranch').andCallFake(() => { - return Promise.resolve(true) - }) - - await repo.refreshStatus() - - waitsFor('the onDidChangeStatuses handler to be called', () => statusHandler.callCount > 0) - }) - - it('emits did-change-statuses if the ahead/behind changes', async () => { - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatuses(statusHandler) - - repo._refreshAheadBehindCount = jasmine.createSpy('_refreshAheadBehindCount').andCallFake(() => { - return Promise.resolve(true) - }) - - await repo.refreshStatus() - - waitsFor('the onDidChangeStatuses handler to be called', () => statusHandler.callCount > 0) - }) - }) - - describe('.isProjectAtRoot()', () => { - it('returns true when the repository is at the root', async () => { - const workingDirectory = copyRepository() - atom.project.setPaths([workingDirectory]) - const repo = atom.project.getRepositories()[0].async - - const atRoot = await repo.isProjectAtRoot() - expect(atRoot).toBe(true) - }) - - it("returns false when the repository wasn't created with a project", async () => { - const workingDirectory = copyRepository() - const repo = GitRepositoryAsync.open(workingDirectory) - - const atRoot = await repo.isProjectAtRoot() - expect(atRoot).toBe(false) - }) - }) - - describe('buffer events', () => { - let repo - - beforeEach(() => { - const workingDirectory = copyRepository() - atom.project.setPaths([workingDirectory]) - - // When the path is added to the project, the repository is refreshed. We - // need to wait for that to complete before the tests continue so that - // we're in a known state. - repo = atom.project.getRepositories()[0].async - waitsForPromise(() => repo.refreshStatus()) - }) - - it('emits a status-changed event when a buffer is saved', async () => { - const editor = await atom.workspace.open('other.txt') - - editor.insertNewline() - - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatus(statusHandler) - editor.save() - - waitsFor('the onDidChangeStatus handler to be called', () => statusHandler.callCount > 0) - runs(() => { - expect(statusHandler.callCount).toBeGreaterThan(0) - expect(statusHandler).toHaveBeenCalledWith({path: editor.getPath(), pathStatus: 256}) - }) - }) - - it('emits a status-changed event when a buffer is reloaded', async () => { - const editor = await atom.workspace.open('other.txt') - - fs.writeFileSync(editor.getPath(), 'changed') - - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatus(statusHandler) - editor.getBuffer().reload() - - waitsFor('the onDidChangeStatus handler to be called', () => statusHandler.callCount > 0) - runs(() => { - expect(statusHandler.callCount).toBeGreaterThan(0) - expect(statusHandler).toHaveBeenCalledWith({path: editor.getPath(), pathStatus: 256}) - }) - }) - - it("emits a status-changed event when a buffer's path changes", async () => { - const editor = await atom.workspace.open('other.txt') - - fs.writeFileSync(editor.getPath(), 'changed') - - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatus(statusHandler) - editor.getBuffer().emitter.emit('did-change-path') - - waitsFor('the onDidChangeStatus handler to be called', () => statusHandler.callCount > 0) - runs(() => { - expect(statusHandler.callCount).toBeGreaterThan(0) - expect(statusHandler).toHaveBeenCalledWith({path: editor.getPath(), pathStatus: 256}) - - const pathHandler = jasmine.createSpy('pathHandler') - const buffer = editor.getBuffer() - buffer.onDidChangePath(pathHandler) - buffer.emitter.emit('did-change-path') - - waitsFor('the onDidChangePath handler to be called', () => pathHandler.callCount > 0) - runs(() => expect(pathHandler.callCount).toBeGreaterThan(0)) - }) - }) - - it('stops listening to the buffer when the repository is destroyed (regression)', async () => { - const editor = await atom.workspace.open('other.txt') - const repo = atom.project.getRepositories()[0] - repo.destroy() - expect(() => editor.save()).not.toThrow() - }) - }) - - describe('when a project is deserialized', () => { - let project2 - - beforeEach(() => { - atom.project.setPaths([copyRepository()]) - - // See the comment in the 'buffer events' beforeEach for why we need to do - // this. - const repository = atom.project.getRepositories()[0].async - waitsForPromise(() => repository.refreshStatus()) - }) - - afterEach(() => { - if (project2) project2.destroy() - }) - - it('subscribes to all the serialized buffers in the project', async () => { - await atom.workspace.open('file.txt') - - project2 = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm, applicationDelegate: atom.applicationDelegate}) - project2.deserialize(atom.project.serialize({isUnloading: true})) - - const repo = project2.getRepositories()[0].async - waitsForPromise(() => repo.refreshStatus()) - runs(() => { - const buffer = project2.getBuffers()[0] - - waitsFor(() => buffer.loaded) - runs(() => { - buffer.append('changes') - - const statusHandler = jasmine.createSpy('statusHandler') - repo.onDidChangeStatus(statusHandler) - buffer.save() - - waitsFor(() => statusHandler.callCount > 0) - runs(() => { - expect(statusHandler.callCount).toBeGreaterThan(0) - expect(statusHandler).toHaveBeenCalledWith({path: buffer.getPath(), pathStatus: 256}) - }) - }) - }) - }) - }) - - describe('GitRepositoryAsync::relativize(filePath, workdir)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - // This is a change in implementation from the git-utils version - it('just returns path if workdir is not provided', () => { - const _path = '/foo/bar/baz.txt' - const relPath = repo.relativize(_path) - expect(_path).toEqual(relPath) - }) - - it('relativizes a repo path', () => { - const workdir = '/tmp/foo/bar/baz/' - const relativizedPath = repo.relativize(`${workdir}a/b.txt`, workdir) - expect(relativizedPath).toBe('a/b.txt') - }) - - it("doesn't require workdir to end in a slash", () => { - const workdir = '/tmp/foo/bar/baz' - const relativizedPath = repo.relativize(`${workdir}/a/b.txt`, workdir) - expect(relativizedPath).toBe('a/b.txt') - }) - - it('preserves file case', () => { - repo.isCaseInsensitive = true - - const workdir = '/tmp/foo/bar/baz/' - const relativizedPath = repo.relativize(`${workdir}a/README.txt`, workdir) - expect(relativizedPath).toBe('a/README.txt') - }) - }) - - describe('.getShortHead(path)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the human-readable branch name', async () => { - const head = await repo.getShortHead() - expect(head).toBe('master') - }) - - describe('in a submodule', () => { - beforeEach(() => { - const workingDirectory = copySubmoduleRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the human-readable branch name', async () => { - await repo.refreshStatus() - - const head = await repo.getShortHead('jstips') - expect(head).toBe('test') - }) - }) - }) - - describe('.isSubmodule(path)', () => { - beforeEach(() => { - const workingDirectory = copySubmoduleRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it("returns false for a path that isn't a submodule", async () => { - const isSubmodule = await repo.isSubmodule('README') - expect(isSubmodule).toBe(false) - }) - - it('returns true for a path that is a submodule', async () => { - const isSubmodule = await repo.isSubmodule('jstips') - expect(isSubmodule).toBe(true) - }) - }) - - describe('.getAheadBehindCount(reference, path)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns 0, 0 for a branch with no upstream', async () => { - const {ahead, behind} = await repo.getAheadBehindCount('master') - expect(ahead).toBe(0) - expect(behind).toBe(0) - }) - }) - - describe('.getCachedUpstreamAheadBehindCount(path)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns 0, 0 for a branch with no upstream', async () => { - await repo.refreshStatus() - - const {ahead, behind} = await repo.getCachedUpstreamAheadBehindCount() - expect(ahead).toBe(0) - expect(behind).toBe(0) - }) - - describe('in a submodule', () => { - beforeEach(() => { - const workingDirectory = copySubmoduleRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns 1, 0 for a branch which is ahead by 1', async () => { - await repo.refreshStatus() - - const {ahead, behind} = await repo.getCachedUpstreamAheadBehindCount('You-Dont-Need-jQuery') - expect(ahead).toBe(1) - expect(behind).toBe(0) - }) - }) - }) - - describe('.getDiffStats(path)', () => { - let workingDirectory - beforeEach(() => { - workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the diff stat', async () => { - const filePath = path.join(workingDirectory, 'a.txt') - fs.writeFileSync(filePath, 'change') - - const {added, deleted} = await repo.getDiffStats('a.txt') - expect(added).toBe(1) - expect(deleted).toBe(0) - }) - }) - - describe('.hasBranch(branch)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('resolves true when the branch exists', async () => { - const hasBranch = await repo.hasBranch('master') - expect(hasBranch).toBe(true) - }) - - it("resolves false when the branch doesn't exist", async () => { - const hasBranch = await repo.hasBranch('trolleybus') - expect(hasBranch).toBe(false) - }) - }) - - describe('.getReferences(path)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the heads, remotes, and tags', async () => { - const {heads, remotes, tags} = await repo.getReferences() - expect(heads.length).toBe(1) - expect(remotes.length).toBe(0) - expect(tags.length).toBe(0) - }) - }) - - describe('.getReferenceTarget(reference, path)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the SHA target', async () => { - const SHA = await repo.getReferenceTarget('refs/heads/master') - expect(SHA).toBe('8a9c86f1cb1f14b8f436eb91f4b052c8802ca99e') - }) - }) - - describe('.getConfigValue(key, path)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('looks up the value for the key', async () => { - const bare = await repo.getConfigValue('core.bare') - expect(bare).toBe('false') - }) - - it("resolves to null if there's no value", async () => { - const value = await repo.getConfigValue('my.special.key') - expect(value).toBeNull() - }) - }) - - describe('.checkoutReference(reference, create)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('can create new branches', () => { - let success = false - let threw = false - waitsForPromise(() => repo.checkoutReference('my-b', true) - .then(_ => success = true) - .catch(_ => threw = true)) - runs(() => { - expect(success).toBe(true) - expect(threw).toBe(false) - }) - }) - }) - - describe('.getLineDiffs(path, text)', () => { - beforeEach(() => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the old and new lines of the diff', async () => { - const [{oldStart, newStart, oldLines, newLines}] = await repo.getLineDiffs('a.txt', 'hi there') - expect(oldStart).toBe(0) - expect(oldLines).toBe(0) - expect(newStart).toBe(1) - expect(newLines).toBe(1) - }) - }) - - describe('GitRepositoryAsync::relativizeToWorkingDirectory(_path)', () => { - let workingDirectory - - beforeEach(() => { - workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('relativizes the given path to the working directory of the repository', async () => { - let absolutePath = path.join(workingDirectory, 'a.txt') - expect(await repo.relativizeToWorkingDirectory(absolutePath)).toBe('a.txt') - absolutePath = path.join(workingDirectory, 'a/b/c.txt') - expect(await repo.relativizeToWorkingDirectory(absolutePath)).toBe('a/b/c.txt') - expect(await repo.relativizeToWorkingDirectory('a.txt')).toBe('a.txt') - expect(await repo.relativizeToWorkingDirectory('/not/in/workdir')).toBe('/not/in/workdir') - expect(await repo.relativizeToWorkingDirectory(null)).toBe(null) - expect(await repo.relativizeToWorkingDirectory()).toBe(undefined) - expect(await repo.relativizeToWorkingDirectory('')).toBe('') - expect(await repo.relativizeToWorkingDirectory(workingDirectory)).toBe('') - }) - - describe('when the opened path is a symlink', () => { - it('relativizes against both the linked path and real path', async () => { - // Symlinks require admin privs on windows so we just skip this there, - // done in git-utils as well - if (process.platform === 'win32') { - return - } - - const linkDirectory = path.join(temp.mkdirSync('atom-working-dir-symlink'), 'link') - fs.symlinkSync(workingDirectory, linkDirectory) - const linkedRepo = GitRepositoryAsync.open(linkDirectory) - expect(await linkedRepo.relativizeToWorkingDirectory(path.join(workingDirectory, 'test1'))).toBe('test1') - expect(await linkedRepo.relativizeToWorkingDirectory(path.join(linkDirectory, 'test2'))).toBe('test2') - expect(await linkedRepo.relativizeToWorkingDirectory(path.join(linkDirectory, 'test2/test3'))).toBe('test2/test3') - expect(await linkedRepo.relativizeToWorkingDirectory('test2/test3')).toBe('test2/test3') - }) - - it('handles case insensitive filesystems', async () => { - repo.isCaseInsensitive = true - expect(await repo.relativizeToWorkingDirectory(path.join(workingDirectory.toUpperCase(), 'a.txt'))).toBe('a.txt') - expect(await repo.relativizeToWorkingDirectory(path.join(workingDirectory.toUpperCase(), 'a/b/c.txt'))).toBe('a/b/c.txt') - }) - }) - }) - - describe('.getOriginURL()', () => { - beforeEach(() => { - const workingDirectory = copyRepository('repo-with-submodules') - repo = GitRepositoryAsync.open(workingDirectory) - }) - - it('returns the origin URL', async () => { - const url = await repo.getOriginURL() - expect(url).toBe('git@github.com:atom/some-repo-i-guess.git') - }) - }) - - describe('.getUpstreamBranch()', () => { - it('returns null when there is no upstream branch', async () => { - const workingDirectory = copyRepository() - repo = GitRepositoryAsync.open(workingDirectory) - - const upstream = await repo.getUpstreamBranch() - expect(upstream).toBe(null) - }) - - it('returns the upstream branch', async () => { - const workingDirectory = copyRepository('repo-with-submodules') - repo = GitRepositoryAsync.open(workingDirectory) - - const upstream = await repo.getUpstreamBranch() - expect(upstream).toBe('refs/remotes/origin/master') - }) - }) -}) diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index 21624c452..ef87d83ee 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -25,16 +25,6 @@ describe "GitRepository", -> it "returns null when no repository is found", -> expect(GitRepository.open(path.join(temp.dir, 'nogit.txt'))).toBeNull() - describe ".async", -> - it "returns a GitRepositoryAsync for the same repo", -> - repoPath = path.join(__dirname, 'fixtures', 'git', 'master.git') - repo = new GitRepository(repoPath) - onSuccess = jasmine.createSpy('onSuccess') - waitsForPromise -> - repo.async.getPath().then(onSuccess) - runs -> - expect(onSuccess.mostRecentCall.args[0]).toEqualPath(repoPath) - describe "new GitRepository(path)", -> it "throws an exception when no repository is found", -> expect(-> new GitRepository(path.join(temp.dir, 'nogit.txt'))).toThrow() diff --git a/src/git-repository-async.js b/src/git-repository-async.js deleted file mode 100644 index 66b73ba77..000000000 --- a/src/git-repository-async.js +++ /dev/null @@ -1,558 +0,0 @@ -'use babel' - -import {Repository} from 'ohnogit' -import {CompositeDisposable, Disposable} from 'event-kit' - -// For the most part, this class behaves the same as `GitRepository`, with a few -// notable differences: -// * Errors are generally propagated out to the caller instead of being -// swallowed within `GitRepositoryAsync`. -// * Methods accepting a path shouldn't be given a null path, unless it is -// specifically allowed as noted in the method's documentation. -export default class GitRepositoryAsync { - static open (path, options = {}) { - // QUESTION: Should this wrap Git.Repository and reject with a nicer message? - return new GitRepositoryAsync(path, options) - } - - static get Git () { - return Repository.Git - } - - // The name of the error thrown when an action is attempted on a destroyed - // repository. - static get DestroyedErrorName () { - return Repository.DestroyedErrorName - } - - constructor (_path, options = {}) { - this.repo = Repository.open(_path, options) - - this.subscriptions = new CompositeDisposable() - - let {refreshOnWindowFocus = true} = options - if (refreshOnWindowFocus) { - const onWindowFocus = () => this.refreshStatus() - window.addEventListener('focus', onWindowFocus) - this.subscriptions.add(new Disposable(() => window.removeEventListener('focus', onWindowFocus))) - } - - const {project, subscribeToBuffers} = options - this.project = project - if (this.project && subscribeToBuffers) { - this.project.getBuffers().forEach(buffer => this.subscribeToBuffer(buffer)) - this.subscriptions.add(this.project.onDidAddBuffer(buffer => this.subscribeToBuffer(buffer))) - } - } - - // This exists to provide backwards compatibility. - get _refreshingPromise () { - return this.repo._refreshingPromise - } - - get openedPath () { - return this.repo.openedPath - } - - // Public: Destroy this {GitRepositoryAsync} object. - // - // This destroys any tasks and subscriptions and releases the underlying - // libgit2 repository handle. This method is idempotent. - destroy () { - this.repo.destroy() - - if (this.subscriptions) { - this.subscriptions.dispose() - this.subscriptions = null - } - } - - // Event subscription - // ================== - - // Public: Invoke the given callback when this GitRepositoryAsync's destroy() - // method is invoked. - // - // * `callback` {Function} - // - // Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. - onDidDestroy (callback) { - return this.repo.onDidDestroy(callback) - } - - // Public: Invoke the given callback when a specific file's status has - // changed. When a file is updated, reloaded, etc, and the status changes, this - // will be fired. - // - // * `callback` {Function} - // * `event` {Object} - // * `path` {String} the old parameters the decoration used to have - // * `pathStatus` {Number} representing the status. This value can be passed to - // {::isStatusModified} or {::isStatusNew} to get more information. - // - // Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. - onDidChangeStatus (callback) { - return this.repo.onDidChangeStatus(callback) - } - - // Public: Invoke the given callback when a multiple files' statuses have - // changed. For example, on window focus, the status of all the paths in the - // repo is checked. If any of them have changed, this will be fired. Call - // {::getPathStatus(path)} to get the status for your path of choice. - // - // * `callback` {Function} - // - // Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. - onDidChangeStatuses (callback) { - return this.repo.onDidChangeStatuses(callback) - } - - // Repository details - // ================== - - // Public: A {String} indicating the type of version control system used by - // this repository. - // - // Returns `"git"`. - getType () { - return 'git' - } - - // Public: Returns a {Promise} which resolves to the {String} path of the - // repository. - getPath () { - return this.repo.getPath() - } - - // Public: Returns a {Promise} which resolves to the {String} working - // directory path of the repository. - getWorkingDirectory (_path) { - return this.repo.getWorkingDirectory() - } - - // Public: Returns a {Promise} that resolves to true if at the root, false if - // in a subfolder of the repository. - isProjectAtRoot () { - if (!this.project) return Promise.resolve(false) - - if (!this.projectAtRoot) { - this.projectAtRoot = this.getWorkingDirectory() - .then(wd => this.project.relativize(wd) === '') - } - - return this.projectAtRoot - } - - // Public: Makes a path relative to the repository's working directory. - // - // * `path` The {String} path to relativize. - // - // Returns a {Promise} which resolves to the relative {String} path. - relativizeToWorkingDirectory (_path) { - return this.repo.relativizeToWorkingDirectory(_path) - } - - // Public: Makes a path relative to the repository's working directory. - // - // * `path` The {String} path to relativize. - // * `workingDirectory` The {String} working directory path. - // - // Returns the relative {String} path. - relativize (_path, workingDirectory) { - return this.repo.relativize(_path, workingDirectory) - } - - // Public: Returns a {Promise} which resolves to whether the given branch - // exists. - hasBranch (branch) { - return this.repo.hasBranch(branch) - } - - // Public: Retrieves a shortened version of the HEAD reference value. - // - // This removes the leading segments of `refs/heads`, `refs/tags`, or - // `refs/remotes`. It also shortens the SHA-1 of a detached `HEAD` to 7 - // characters. - // - // * `path` An optional {String} path in the repository to get this information - // for, only needed if the repository contains submodules. - // - // Returns a {Promise} which resolves to a {String}. - getShortHead (_path) { - return this.repo.getShortHead(_path) - } - - // Public: Is the given path a submodule in the repository? - // - // * `path` The {String} path to check. - // - // Returns a {Promise} that resolves true if the given path is a submodule in - // the repository. - isSubmodule (_path) { - return this.repo.isSubmodule(_path) - } - - // Public: Returns the number of commits behind the current branch is from the - // its upstream remote branch. - // - // * `reference` The {String} branch reference name. - // * `path` The {String} path in the repository to get this information - // for, only needed if the repository contains submodules. - // - // Returns a {Promise} which resolves to an {Object} with the following keys: - // * `ahead` The {Number} of commits ahead. - // * `behind` The {Number} of commits behind. - getAheadBehindCount (reference, _path) { - return this.repo.getAheadBehindCount(reference, _path) - } - - // Public: Get the cached ahead/behind commit counts for the current branch's - // upstream branch. - // - // * `path` An optional {String} path in the repository to get this information - // for, only needed if the repository has submodules. - // - // Returns a {Promise} which resolves to an {Object} with the following keys: - // * `ahead` The {Number} of commits ahead. - // * `behind` The {Number} of commits behind. - getCachedUpstreamAheadBehindCount (_path) { - return this.repo.getCachedUpstreamAheadBehindCount(_path) - } - - // Public: Returns the git configuration value specified by the key. - // - // * `path` An optional {String} path in the repository to get this information - // for, only needed if the repository has submodules. - // - // Returns a {Promise} which resolves to the {String} git configuration value - // specified by the key. - getConfigValue (key, _path) { - return this.repo.getConfigValue(key, _path) - } - - // Public: Get the URL for the 'origin' remote. - // - // * `path` (optional) {String} path in the repository to get this information - // for, only needed if the repository has submodules. - // - // Returns a {Promise} which resolves to the {String} origin url of the - // repository. - getOriginURL (_path) { - return this.repo.getOriginURL(_path) - } - - // Public: Returns the upstream branch for the current HEAD, or null if there - // is no upstream branch for the current HEAD. - // - // * `path` An optional {String} path in the repo to get this information for, - // only needed if the repository contains submodules. - // - // Returns a {Promise} which resolves to a {String} branch name such as - // `refs/remotes/origin/master`. - getUpstreamBranch (_path) { - return this.repo.getUpstreamBranch(_path) - } - - // Public: Gets all the local and remote references. - // - // * `path` An optional {String} path in the repository to get this information - // for, only needed if the repository has submodules. - // - // Returns a {Promise} which resolves to an {Object} with the following keys: - // * `heads` An {Array} of head reference names. - // * `remotes` An {Array} of remote reference names. - // * `tags` An {Array} of tag reference names. - getReferences (_path) { - return this.repo.getReferences(_path) - } - - // Public: Get the SHA for the given reference. - // - // * `reference` The {String} reference to get the target of. - // * `path` An optional {String} path in the repo to get the reference target - // for. Only needed if the repository contains submodules. - // - // Returns a {Promise} which resolves to the current {String} SHA for the - // given reference. - getReferenceTarget (reference, _path) { - return this.repo.getReferenceTarget(reference, _path) - } - - // Reading Status - // ============== - - // Public: Resolves true if the given path is modified. - // - // * `path` The {String} path to check. - // - // Returns a {Promise} which resolves to a {Boolean} that's true if the `path` - // is modified. - isPathModified (_path) { - return this.repo.isPathModified(_path) - } - - // Public: Resolves true if the given path is new. - // - // * `path` The {String} path to check. - // - // Returns a {Promise} which resolves to a {Boolean} that's true if the `path` - // is new. - isPathNew (_path) { - return this.repo.isPathNew(_path) - } - - // Public: Is the given path ignored? - // - // * `path` The {String} path to check. - // - // Returns a {Promise} which resolves to a {Boolean} that's true if the `path` - // is ignored. - isPathIgnored (_path) { - return this.repo.isPathIgnored(_path) - } - - // Get the status of a directory in the repository's working directory. - // - // * `directoryPath` The {String} path to check. - // - // Returns a {Promise} resolving to a {Number} representing the status. This - // value can be passed to {::isStatusModified} or {::isStatusNew} to get more - // information. - getDirectoryStatus (directoryPath) { - return this.repo.getDirectoryStatus(directoryPath) - } - - // Refresh the status bit for the given path. - // - // Note that if the status of the path has changed, this will emit a - // 'did-change-status' event. - // - // * `path` The {String} path whose status should be refreshed. - // - // Returns a {Promise} which resolves to a {Number} which is the refreshed - // status bit for the path. - refreshStatusForPath (_path) { - return this.repo.refreshStatusForPath(_path) - } - - // Returns a Promise that resolves to the status bit of a given path if it has - // one, otherwise 'current'. - getPathStatus (_path) { - return this.refreshStatusForPath(_path) - } - - // Public: Get the cached status for the given path. - // - // * `path` A {String} path in the repository, relative or absolute. - // - // Returns a {Promise} which resolves to a status {Number} or null if the - // path is not in the cache. - getCachedPathStatus (_path) { - return this.repo.getCachedPathStatus(_path) - } - - // Public: Get the cached statuses for the repository. - // - // Returns an {Object} of {Number} statuses, keyed by {String} working - // directory-relative file names. - getCachedPathStatuses () { - return this.repo.pathStatusCache - } - - // Public: Returns true if the given status indicates modification. - // - // * `statusBit` A {Number} representing the status. - // - // Returns a {Boolean} that's true if the `statusBit` indicates modification. - isStatusModified (statusBit) { - return this.repo.isStatusModified(statusBit) - } - - // Public: Returns true if the given status indicates a new path. - // - // * `statusBit` A {Number} representing the status. - // - // Returns a {Boolean} that's true if the `statusBit` indicates a new path. - isStatusNew (statusBit) { - return this.repo.isStatusNew(statusBit) - } - - // Public: Returns true if the given status indicates the path is staged. - // - // * `statusBit` A {Number} representing the status. - // - // Returns a {Boolean} that's true if the `statusBit` indicates the path is - // staged. - isStatusStaged (statusBit) { - return this.repo.isStatusStaged(statusBit) - } - - // Public: Returns true if the given status indicates the path is ignored. - // - // * `statusBit` A {Number} representing the status. - // - // Returns a {Boolean} that's true if the `statusBit` indicates the path is - // ignored. - isStatusIgnored (statusBit) { - return this.repo.isStatusIgnored(statusBit) - } - - // Public: Returns true if the given status indicates the path is deleted. - // - // * `statusBit` A {Number} representing the status. - // - // Returns a {Boolean} that's true if the `statusBit` indicates the path is - // deleted. - isStatusDeleted (statusBit) { - return this.repo.isStatusDeleted(statusBit) - } - - // Retrieving Diffs - // ================ - // Public: Retrieves the number of lines added and removed to a path. - // - // This compares the working directory contents of the path to the `HEAD` - // version. - // - // * `path` The {String} path to check. - // - // Returns a {Promise} which resolves to an {Object} with the following keys: - // * `added` The {Number} of added lines. - // * `deleted` The {Number} of deleted lines. - getDiffStats (_path) { - return this.repo.getDiffStats(_path) - } - - // Public: Retrieves the line diffs comparing the `HEAD` version of the given - // path and the given text. - // - // * `path` The {String} path relative to the repository. - // * `text` The {String} to compare against the `HEAD` contents - // - // Returns an {Array} of hunk {Object}s with the following keys: - // * `oldStart` The line {Number} of the old hunk. - // * `newStart` The line {Number} of the new hunk. - // * `oldLines` The {Number} of lines in the old hunk. - // * `newLines` The {Number} of lines in the new hunk - getLineDiffs (_path, text) { - return this.repo.getLineDiffs(_path, text) - } - - // Checking Out - // ============ - - // Public: Restore the contents of a path in the working directory and index - // to the version at `HEAD`. - // - // This is essentially the same as running: - // - // ```sh - // git reset HEAD -- - // git checkout HEAD -- - // ``` - // - // * `path` The {String} path to checkout. - // - // Returns a {Promise} that resolves or rejects depending on whether the - // method was successful. - checkoutHead (_path) { - return this.repo.checkoutHead(_path) - } - - // Public: Checks out a branch in your repository. - // - // * `reference` The {String} reference to checkout. - // * `create` A {Boolean} value which, if true creates the new reference if - // it doesn't exist. - // - // Returns a {Promise} that resolves if the method was successful. - checkoutReference (reference, create) { - return this.repo.checkoutReference(reference, create) - } - - // Private - // ======= - - checkoutHeadForEditor (editor) { - const filePath = editor.getPath() - if (!filePath) { - return Promise.reject() - } - - if (editor.buffer.isModified()) { - editor.buffer.reload() - } - - return this.checkoutHead(filePath) - } - - // Refreshes the git status. - // - // Returns a {Promise} which will resolve to {null} when refresh is complete. - refreshStatus () { - let projectPathsPromises = [Promise.resolve('')] - if (this.project) { - projectPathsPromises = this.project.getPaths() - .map(p => this.relativizeToWorkingDirectory(p)) - } - - return Promise.all(projectPathsPromises) - .then(paths => paths.map(p => p.length > 0 ? p + '/**' : '*')) - .then(pathspecs => this.repo.refreshStatus(pathspecs)) - } - - // Get the NodeGit repository for the given path. - // - // * `path` The optional {String} path within the repository. This is only - // needed if you want to get the repository for that path if it is a - // submodule. - // - // Returns a {Promise} which resolves to the {NodeGit.Repository}. - getRepo (_path) { - return this.repo.getRepo(_path) - } - - // Open a new instance of the underlying {NodeGit.Repository}. - // - // By opening multiple connections to the same underlying repository, users - // can safely access the same repository concurrently. - // - // Returns the new {NodeGit.Repository}. - openRepository () { - return this.repo.openRepository() - } - - // Section: Private - // ================ - - // Has the repository been destroyed? - // - // Returns a {Boolean}. - _isDestroyed () { - return this.repo._isDestroyed() - } - - // Subscribe to events on the given buffer. - subscribeToBuffer (buffer) { - const bufferSubscriptions = new CompositeDisposable() - - const refreshStatusForBuffer = () => { - const _path = buffer.getPath() - if (_path) { - this.refreshStatusForPath(_path) - } - } - - bufferSubscriptions.add( - buffer.onDidSave(refreshStatusForBuffer), - buffer.onDidReload(refreshStatusForBuffer), - buffer.onDidChangePath(refreshStatusForBuffer), - buffer.onDidDestroy(() => { - bufferSubscriptions.dispose() - this.subscriptions.remove(bufferSubscriptions) - }) - ) - - this.subscriptions.add(bufferSubscriptions) - } -} diff --git a/src/git-repository.coffee b/src/git-repository.coffee index 6f0851cf9..3a2477bc8 100644 --- a/src/git-repository.coffee +++ b/src/git-repository.coffee @@ -3,7 +3,6 @@ _ = require 'underscore-plus' {Emitter, Disposable, CompositeDisposable} = require 'event-kit' fs = require 'fs-plus' -GitRepositoryAsync = require './git-repository-async' GitUtils = require 'git-utils' Task = require './task' @@ -76,13 +75,6 @@ class GitRepository unless @repo? throw new Error("No Git repository found searching path: #{path}") - asyncOptions = _.clone(options) - # GitRepository itself will handle these cases by manually calling through - # to the async repo. - asyncOptions.refreshOnWindowFocus = false - asyncOptions.subscribeToBuffers = false - @async = GitRepositoryAsync.open(path, asyncOptions) - @statuses = {} @upstream = {ahead: 0, behind: 0} for submodulePath, submoduleRepo of @repo.submodules From a973e1ae9e6c3318ddfd0fe3c144e1d275244d38 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Jul 2016 14:04:58 -0700 Subject: [PATCH 043/160] Put back GitRepository::isDestroyed() method --- src/git-repository.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/git-repository.coffee b/src/git-repository.coffee index 3a2477bc8..85600bba7 100644 --- a/src/git-repository.coffee +++ b/src/git-repository.coffee @@ -117,6 +117,10 @@ class GitRepository @subscriptions.dispose() @subscriptions = null + # Public: Returns a {Boolean} indicating if this repository has been destroyed. + isDestroyed: -> + not @repo? + # Public: Invoke the given callback when this GitRepository's destroy() method # is invoked. # From 47df8c5d77d86dcc5038a6121ed500e4a51ec6af Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Jul 2016 14:37:37 -0700 Subject: [PATCH 044/160] Upgrade packages to use sync git repository again Signed-off-by: Nathan Sobo --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 186c22ecc..1829a077b 100644 --- a/package.json +++ b/package.json @@ -93,8 +93,8 @@ "encoding-selector": "0.22.0", "exception-reporting": "0.38.1", "find-and-replace": "0.201.0", - "fuzzy-finder": "1.2.0", - "git-diff": "1.0.1", + "fuzzy-finder": "1.3.0-sync-git", + "git-diff": "1.1.0-sync-git", "go-to-line": "0.31.0", "grammar-selector": "0.48.1", "image-view": "0.58.2", @@ -105,12 +105,12 @@ "markdown-preview": "0.158.0", "metrics": "0.53.1", "notifications": "0.65.0", - "open-on-github": "1.1.0", + "open-on-github": "1.2.0-sync-git", "package-generator": "1.0.0", "settings-view": "0.240.1", "snippets": "1.0.2", "spell-check": "0.67.1", - "status-bar": "1.3.1", + "status-bar": "1.4.0-sync-git", "styleguide": "0.47.0", "symbols-view": "0.113.0", "tabs": "0.99.0", From 678d5b4c247ae63cce2bc73a383cb6a493d4eb89 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Jul 2016 15:41:10 -0700 Subject: [PATCH 045/160] Remove usage of repository.async in Workspace Signed-off-by: Nathan Sobo --- src/workspace.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index bde2a62d3..8d0ff38fd 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -1097,7 +1097,7 @@ class Workspace extends Model checkoutHead = => @project.repositoryForDirectory(new Directory(editor.getDirectoryPath())) .then (repository) -> - repository?.async.checkoutHeadForEditor(editor) + repository?.checkoutHeadForEditor(editor) if @config.get('editor.confirmCheckoutHeadRevision') @applicationDelegate.confirm From 35aee0b8e49f3e85442847176076cb248d0bedf8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 14 Jul 2016 17:01:26 +0200 Subject: [PATCH 046/160] Use nvm on Linux --- script/cibuild-atom-linux | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index 2c3395608..b04d73f62 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -7,10 +7,10 @@ export BUILD_ATOM_RELEASES_S3_KEY=$BUILD_ATOM_LINUX_RELEASES_S3_KEY export BUILD_ATOM_RELEASES_S3_SECRET=$BUILD_ATOM_LINUX_RELEASES_S3_SECRET export BUILD_ATOM_RELEASES_S3_BUCKET=$BUILD_ATOM_LINUX_RELEASES_S3_BUCKET -if [ -d /usr/local/share/nodenv ]; then - export NODENV_ROOT=/usr/local/share/nodenv - export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH - export NODENV_VERSION="v0.10.21" -fi +git clone https://github.com/creationix/nvm.git /tmp/.nvm +source /tmp/.nvm/nvm.sh +nvm install 4.4.7 +nvm use 4.4.7 +npm install -g npm script/cibuild From e3743db892e964a49352c881167cb16f38201b27 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 14 Jul 2016 17:25:58 +0200 Subject: [PATCH 047/160] Use node 4 and npm 3 on rpm --- Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index d792c30c5..37339ccfd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,11 +12,13 @@ RUN yum install -y \ glibc-devel \ git-core \ libgnome-keyring-devel \ - rpmdevtools \ - nodejs \ - npm + rpmdevtools -RUN npm install -g npm@1.4.28 --loglevel error +RUN git clone https://github.com/creationix/nvm.git /tmp/.nvm +RUN source /tmp/.nvm/nvm.sh +RUN nvm install 4.4.7 +RUN nvm use 4.4.7 +RUN npm install -g npm --loglevel error ADD . /atom WORKDIR /atom From e160c725fd2d24b23f18a358340b20df9a816352 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 14 Jul 2016 17:29:42 +0200 Subject: [PATCH 048/160] Use curl for rpm --- Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 37339ccfd..15f8e2898 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,8 @@ # Base docker image FROM fedora:21 +RUN curl --silent --location https://rpm.nodesource.com/setup_4.x | bash - + # Install dependencies RUN yum install -y \ make \ @@ -12,12 +14,10 @@ RUN yum install -y \ glibc-devel \ git-core \ libgnome-keyring-devel \ - rpmdevtools + rpmdevtools \ + nodejs \ + npm -RUN git clone https://github.com/creationix/nvm.git /tmp/.nvm -RUN source /tmp/.nvm/nvm.sh -RUN nvm install 4.4.7 -RUN nvm use 4.4.7 RUN npm install -g npm --loglevel error ADD . /atom From 4092ff1aea60c13c394f10ed30f594e307644c77 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 14 Jul 2016 17:47:45 +0200 Subject: [PATCH 049/160] Use another docker image for rpm --- Dockerfile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 15f8e2898..8f5483b33 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,9 +2,7 @@ # DESCRIPTION: Image to build Atom and create a .rpm file # Base docker image -FROM fedora:21 - -RUN curl --silent --location https://rpm.nodesource.com/setup_4.x | bash - +FROM nodesource/fedora21:4.4.7 # Install dependencies RUN yum install -y \ @@ -14,9 +12,7 @@ RUN yum install -y \ glibc-devel \ git-core \ libgnome-keyring-devel \ - rpmdevtools \ - nodejs \ - npm + rpmdevtools RUN npm install -g npm --loglevel error From 14b74937e12f436ea234c2508b4000ecc256fa7b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 14 Jul 2016 17:50:59 +0200 Subject: [PATCH 050/160] Use 4.2.6 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8f5483b33..22a101743 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # DESCRIPTION: Image to build Atom and create a .rpm file # Base docker image -FROM nodesource/fedora21:4.4.7 +FROM nodesource/fedora21:4.2.6 # Install dependencies RUN yum install -y \ From b674169becad25067dfd80d55eb61100a4a6e8aa Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 14 Jul 2016 18:07:28 +0200 Subject: [PATCH 051/160] Remove previously installed nvm --- script/cibuild-atom-linux | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index b04d73f62..fe79c19fe 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -7,8 +7,9 @@ export BUILD_ATOM_RELEASES_S3_KEY=$BUILD_ATOM_LINUX_RELEASES_S3_KEY export BUILD_ATOM_RELEASES_S3_SECRET=$BUILD_ATOM_LINUX_RELEASES_S3_SECRET export BUILD_ATOM_RELEASES_S3_BUCKET=$BUILD_ATOM_LINUX_RELEASES_S3_BUCKET -git clone https://github.com/creationix/nvm.git /tmp/.nvm -source /tmp/.nvm/nvm.sh +rm -rf /tmp/.atom-nvm +git clone https://github.com/creationix/nvm.git /tmp/.atom-nvm +source /tmp/.atom-nvm/nvm.sh nvm install 4.4.7 nvm use 4.4.7 npm install -g npm From 15cf9fb0d07e104de6e84b8cadb5fdd30fd27ab0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Jul 2016 11:03:45 -0700 Subject: [PATCH 052/160] Upgrade to minor releases of packages --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1829a077b..4083f8a83 100644 --- a/package.json +++ b/package.json @@ -93,8 +93,8 @@ "encoding-selector": "0.22.0", "exception-reporting": "0.38.1", "find-and-replace": "0.201.0", - "fuzzy-finder": "1.3.0-sync-git", - "git-diff": "1.1.0-sync-git", + "fuzzy-finder": "1.3.0", + "git-diff": "1.1.0", "go-to-line": "0.31.0", "grammar-selector": "0.48.1", "image-view": "0.58.2", @@ -105,12 +105,12 @@ "markdown-preview": "0.158.0", "metrics": "0.53.1", "notifications": "0.65.0", - "open-on-github": "1.2.0-sync-git", + "open-on-github": "1.2.0", "package-generator": "1.0.0", "settings-view": "0.240.1", "snippets": "1.0.2", "spell-check": "0.67.1", - "status-bar": "1.4.0-sync-git", + "status-bar": "1.4.0", "styleguide": "0.47.0", "symbols-view": "0.113.0", "tabs": "0.99.0", From f83ebf337caf0e48c0268387208921c23840570e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Jul 2016 12:58:25 -0700 Subject: [PATCH 053/160] Clear out apm folder in cibuild --- script/cibuild | 1 + 1 file changed, 1 insertion(+) diff --git a/script/cibuild b/script/cibuild index 860e0a938..627c2291a 100755 --- a/script/cibuild +++ b/script/cibuild @@ -62,6 +62,7 @@ function removeNodeModules() { try { fsPlus.removeSync(path.resolve(__dirname, '..', 'node_modules')); + fsPlus.removeSync(path.resolve(__dirname, '..', 'apm', 'node_modules')); } catch (error) { console.error(error.message); process.exit(1); From 7a6b7fea062bda17f29789e4c9a7d76348b60a46 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 16 Jul 2016 20:01:54 +0200 Subject: [PATCH 054/160] :arrow_up: apm 1.12.0-beta0 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 3bf1fe769..d8896a2dc 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.11.4" + "atom-package-manager": "1.12.0-beta0" } } From e9623b30b8df945b2aa4913cb0e2a7c55585c0a2 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 16 Jul 2016 20:26:58 +0200 Subject: [PATCH 055/160] Include apm version in the fingerprint --- script/utils/fingerprint.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/script/utils/fingerprint.js b/script/utils/fingerprint.js index c419ba4fd..e1f6276d2 100644 --- a/script/utils/fingerprint.js +++ b/script/utils/fingerprint.js @@ -6,12 +6,14 @@ var fingerprintPath = path.resolve(__dirname, '..', '..', 'node_modules', '.atom module.exports = { fingerprint: function () { - var packageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) + var atomPackageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) + var apmPackageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'apm', 'package.json')) //Include the electron minor version in the fingerprint since that changing requires a re-install - var electronVersion = JSON.parse(packageJson).electronVersion.replace(/\.\d+$/, '') + var electronVersion = JSON.parse(atomPackageJson).electronVersion.replace(/\.\d+$/, '') + var apmVersion = JSON.parse(apmPackageJson).dependencies['atom-package-manager'] - var body = electronVersion + process.platform + process.version + var body = electronVersion + apmVersion + process.platform + process.version return crypto.createHash('sha1').update(body).digest('hex') }, From 59a8c0544b1484f23464e3b03702eb9e712bcebd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 16 Jul 2016 20:40:07 +0200 Subject: [PATCH 056/160] Set a higher timeout for Travis caching phase --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e894731ea..ec039e2ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ install: script: script/cibuild cache: + timeout: 1000 directories: - node_modules - build/node_modules From 35bdaf34a127a80f0b8ae72b6553878fec5ff980 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Sat, 16 Jul 2016 20:42:04 -0400 Subject: [PATCH 057/160] :arrow_up: timecop@0.33.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4083f8a83..76aff5505 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "styleguide": "0.47.0", "symbols-view": "0.113.0", "tabs": "0.99.0", - "timecop": "0.33.1", + "timecop": "0.33.2", "tree-view": "0.208.1", "update-package-dependencies": "0.10.0", "welcome": "0.34.0", From 1610bcedb1faa4eb40973cace746590c1cb31084 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Sun, 17 Jul 2016 22:42:08 -0700 Subject: [PATCH 058/160] Ensure install & upgrade fix up previous shell paths --- src/main-process/squirrel-update.coffee | 32 ++++++++++++++----------- src/main-process/win-shell.coffee | 10 ++++---- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main-process/squirrel-update.coffee b/src/main-process/squirrel-update.coffee index 5dfff6710..5d9910a19 100644 --- a/src/main-process/squirrel-update.coffee +++ b/src/main-process/squirrel-update.coffee @@ -125,31 +125,35 @@ exports.restartAtom = (app) -> app.once 'will-quit', -> Spawner.spawn(path.join(binFolder, 'atom.cmd'), args) app.quit() +updateContextMenus = (callback) -> + WinShell.fileContextMenu.update -> + WinShell.folderContextMenu.update -> + WinShell.folderBackgroundContextMenu.update -> + callback + # Handle squirrel events denoted by --squirrel-* command line arguments. exports.handleStartupEvent = (app, squirrelCommand) -> switch squirrelCommand when '--squirrel-install' createShortcuts -> - WinShell.fileHandler.register -> - addCommandsToPath -> - app.quit() + addCommandsToPath -> + WinShell.fileHandler.register -> + updateContextMenus -> + app.quit() true when '--squirrel-updated' updateShortcuts -> - WinShell.fileHandler.update -> - WinShell.fileContextMenu.update -> - WinShell.folderContextMenu.update -> - WinShell.folderBackgroundContextMenu.update -> - addCommandsToPath -> - app.quit() + addCommandsToPath -> + updateContextMenus -> + app.quit() true when '--squirrel-uninstall' removeShortcuts -> - WinShell.fileHandler.deregister -> - WinShell.fileContextMenu.deregister -> - WinShell.folderContextMenu.deregister -> - WinShell.folderBackgroundContextMenu.deregister -> - removeCommandsFromPath -> + removeCommandsFromPath -> + WinShell.fileHandler.deregister -> + WinShell.fileContextMenu.deregister -> + WinShell.folderContextMenu.deregister -> + WinShell.folderBackgroundContextMenu.deregister -> app.quit() true when '--squirrel-obsolete' diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee index 5e1e1428a..269e9e97c 100644 --- a/src/main-process/win-shell.coffee +++ b/src/main-process/win-shell.coffee @@ -17,7 +17,7 @@ class ShellOption doneCount = @parts.length @parts.forEach((part) => reg = new Registry({hive: 'HKCU', key: if part.key? then "#{@key}\\#{part.key}" else @key}) - reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if doneCount-- is 0)) + reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if --doneCount is 0)) deregister: (callback) => @isRegistered (isRegistered) => if isRegistered @@ -26,11 +26,11 @@ class ShellOption callback null, false update: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) - .get @parts[0].name, (err, val) -> - if err? or not val.value.endsWith '\\' + exeName - callback err, val + .get @parts[0].name, (err, val) => + if err? or not val.value.includes '\\' + exeName + callback(err) else - register callback + @register callback exports.appName = appName From eb7d695e60c75eab1a241521bb7da60ba2a22db6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 18 Jul 2016 15:56:50 +0200 Subject: [PATCH 059/160] Don't run specs to avoid timing out the build ...this needs to be re-enabled on the next commit. --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index b248eda2e..41f22376f 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -288,7 +288,7 @@ module.exports = (grunt) -> ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('mktar') if process.platform is 'linux' - ciTasks.push('test') if process.platform is 'darwin' + # ciTasks.push('test') if process.platform is 'darwin' ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI if process.platform is 'win32' ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL From 7a22c5040335db8b6c92d315a39a3273ddb1816b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 18 Jul 2016 16:51:09 +0200 Subject: [PATCH 060/160] Run tests --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 41f22376f..b248eda2e 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -288,7 +288,7 @@ module.exports = (grunt) -> ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('mktar') if process.platform is 'linux' - # ciTasks.push('test') if process.platform is 'darwin' + ciTasks.push('test') if process.platform is 'darwin' ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI if process.platform is 'win32' ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL From 3b372e270ccdeabda4dfac68ffe1c9d95f189fdc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 18 Jul 2016 17:48:45 +0200 Subject: [PATCH 061/160] Install npm 3 on Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ec039e2ee..13a74c608 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ install: - source /tmp/.nvm/nvm.sh - nvm install $NODE_VERSION - nvm use --delete-prefix $NODE_VERSION + - npm install -g npm script: script/cibuild From 23dfa392c9788ce4433bc4e1cfb19c55aa0de875 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Mon, 18 Jul 2016 22:56:02 -0700 Subject: [PATCH 062/160] Fix up Squirrel specs --- spec/squirrel-update-spec.coffee | 15 ++++++++++----- src/main-process/squirrel-update.coffee | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/spec/squirrel-update-spec.coffee b/spec/squirrel-update-spec.coffee index 51442abc6..2fe944e41 100644 --- a/spec/squirrel-update-spec.coffee +++ b/spec/squirrel-update-spec.coffee @@ -26,11 +26,16 @@ describe "Windows Squirrel Update", -> # do nothing on command, just run passed callback invokeCallback callback - # Prevent any actual change to Windows Shell - for own property of WinShell - for own method of property - spyOn(property, method).andCallFake (callback) -> - invokeCallback callback + # Prevent any actual change to Windows Shell + class FakeShellOption + isRegistered: (callback) -> callback true + register: (callback) -> callback null + deregister: (callback) -> callback null, true + update: (callback) -> callback null + WinShell.fileHandler = new FakeShellOption() + WinShell.fileContextMenu = new FakeShellOption() + WinShell.folderContextMenu = new FakeShellOption() + WinShell.folderBackgroundContextMenu = new FakeShellOption() it "quits the app on all squirrel events", -> app = quit: jasmine.createSpy('quit') diff --git a/src/main-process/squirrel-update.coffee b/src/main-process/squirrel-update.coffee index 5d9910a19..acac81457 100644 --- a/src/main-process/squirrel-update.coffee +++ b/src/main-process/squirrel-update.coffee @@ -129,7 +129,7 @@ updateContextMenus = (callback) -> WinShell.fileContextMenu.update -> WinShell.folderContextMenu.update -> WinShell.folderBackgroundContextMenu.update -> - callback + callback() # Handle squirrel events denoted by --squirrel-* command line arguments. exports.handleStartupEvent = (app, squirrelCommand) -> From 26f48001928f83b1fef598eaf68ae0479f25b4bc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Jul 2016 14:29:03 +0200 Subject: [PATCH 063/160] Try not caching node_modules --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 13a74c608..31cc8016c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,10 +36,8 @@ script: script/cibuild cache: timeout: 1000 directories: - - node_modules - build/node_modules - apm/node_modules - - $HOME/.atom/compile-cache notifications: email: From 5c1a433e2ae40b2c5275a6aca04bb8aba67d243d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Jul 2016 14:56:27 +0200 Subject: [PATCH 064/160] Put back node_modules in the cache --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 31cc8016c..179abece8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,13 +29,13 @@ install: - source /tmp/.nvm/nvm.sh - nvm install $NODE_VERSION - nvm use --delete-prefix $NODE_VERSION - - npm install -g npm script: script/cibuild cache: timeout: 1000 directories: + - node_modules - build/node_modules - apm/node_modules From 25e8d3b1cf875c9bbe244755b8ccc96e14adcc52 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Jul 2016 14:58:58 +0200 Subject: [PATCH 065/160] Add electron to the cache --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 179abece8..3bdd77f4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,9 @@ cache: timeout: 1000 directories: - node_modules - - build/node_modules - apm/node_modules + - build/node_modules + - electron notifications: email: From 207131836d769e75b7ba6e49b240cc51306952f6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Jul 2016 16:04:07 +0200 Subject: [PATCH 066/160] Cache also .atom/.node-gyp/.atom --- .travis.yml | 1 + build/Gruntfile.coffee | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3bdd77f4e..27b6ad1f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ script: script/cibuild cache: timeout: 1000 directories: + - $HOME/.atom/.node-gyp/.atom - node_modules - apm/node_modules - build/node_modules diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index b248eda2e..41f22376f 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -288,7 +288,7 @@ module.exports = (grunt) -> ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('mktar') if process.platform is 'linux' - ciTasks.push('test') if process.platform is 'darwin' + # ciTasks.push('test') if process.platform is 'darwin' ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI if process.platform is 'win32' ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL From 9b4f46cab102ca6345e7d31f5dcb85a022b09111 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Jul 2016 16:56:26 +0200 Subject: [PATCH 067/160] Add back testing to Gruntfile --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 41f22376f..b248eda2e 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -288,7 +288,7 @@ module.exports = (grunt) -> ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('mktar') if process.platform is 'linux' - # ciTasks.push('test') if process.platform is 'darwin' + ciTasks.push('test') if process.platform is 'darwin' ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI if process.platform is 'win32' ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL From 2fb0d68be8cae9aaed6370ebb3ac02250d0dee0f Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Tue, 19 Jul 2016 16:33:29 -0700 Subject: [PATCH 068/160] Blank lines and for x in y syntax from review --- src/main-process/win-shell.coffee | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee index 269e9e97c..39e9f4ed0 100644 --- a/src/main-process/win-shell.coffee +++ b/src/main-process/win-shell.coffee @@ -9,21 +9,25 @@ class ShellOption constructor: (key, parts) -> @key = key @parts = parts + isRegistered: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) .get @parts[0].name, (err, val) => callback(not err? and val.value is @parts[0].value) + register: (callback) => doneCount = @parts.length - @parts.forEach((part) => + for part in @parts reg = new Registry({hive: 'HKCU', key: if part.key? then "#{@key}\\#{part.key}" else @key}) - reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if --doneCount is 0)) + reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if --doneCount is 0) + deregister: (callback) => @isRegistered (isRegistered) => if isRegistered new Registry({hive: 'HKCU', key: @key}).destroy -> callback null, true else callback null, false + update: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) .get @parts[0].name, (err, val) => From b3d3b52d3de21397dd453f08fd0e07f1a9b4f6ba Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 10:50:32 +0200 Subject: [PATCH 069/160] Disable specs (again) to allow caching --- build/Gruntfile.coffee | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index b248eda2e..ad445a6ce 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -282,21 +282,21 @@ module.exports = (grunt) -> ciTasks.push('output-disk-space') unless process.env.CI ciTasks.push('download-electron') ciTasks.push('download-electron-chromedriver') - ciTasks.push('build') + # ciTasks.push('build') ciTasks.push('fingerprint') - ciTasks.push('dump-symbols') if process.platform is 'darwin' - ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') - ciTasks.push('mkdeb') if process.platform is 'linux' - ciTasks.push('mktar') if process.platform is 'linux' - ciTasks.push('test') if process.platform is 'darwin' - ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI - if process.platform is 'win32' - ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL - ciTasks.push('codesign:installer-deferred') if not process.env.JANKY_SIGNTOOL - ciTasks.push('create-windows-installer:installer') - ciTasks.push('codesign:installer') if process.env.JANKY_SIGNTOOL - ciTasks.push('codesign:cleanup') - ciTasks.push('publish-build') unless process.env.CI + # ciTasks.push('dump-symbols') if process.platform is 'darwin' + # ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') + # ciTasks.push('mkdeb') if process.platform is 'linux' + # ciTasks.push('mktar') if process.platform is 'linux' + # ciTasks.push('test') if process.platform is 'darwin' + # ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI + # if process.platform is 'win32' + # ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL + # ciTasks.push('codesign:installer-deferred') if not process.env.JANKY_SIGNTOOL + # ciTasks.push('create-windows-installer:installer') + # ciTasks.push('codesign:installer') if process.env.JANKY_SIGNTOOL + # ciTasks.push('codesign:cleanup') + # ciTasks.push('publish-build') unless process.env.CI grunt.registerTask('ci', ciTasks) From d2cb36e3a09a5ef7e6c0c8384b5ca3e28285af52 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 12:26:02 +0200 Subject: [PATCH 070/160] :arrow_up: apm 1.12.1 --- .travis.yml | 1 - apm/package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 27b6ad1f3..3bdd77f4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,6 @@ script: script/cibuild cache: timeout: 1000 directories: - - $HOME/.atom/.node-gyp/.atom - node_modules - apm/node_modules - build/node_modules diff --git a/apm/package.json b/apm/package.json index d8896a2dc..69aeaa413 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.12.0-beta0" + "atom-package-manager": "1.12.1" } } From be134ce3c95d54ddc2e60a40a88f340be924100f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 13:01:00 +0200 Subject: [PATCH 071/160] Revert "Disable specs (again) to allow caching" This reverts commit b3d3b52d3de21397dd453f08fd0e07f1a9b4f6ba. --- build/Gruntfile.coffee | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index ad445a6ce..b248eda2e 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -282,21 +282,21 @@ module.exports = (grunt) -> ciTasks.push('output-disk-space') unless process.env.CI ciTasks.push('download-electron') ciTasks.push('download-electron-chromedriver') - # ciTasks.push('build') + ciTasks.push('build') ciTasks.push('fingerprint') - # ciTasks.push('dump-symbols') if process.platform is 'darwin' - # ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') - # ciTasks.push('mkdeb') if process.platform is 'linux' - # ciTasks.push('mktar') if process.platform is 'linux' - # ciTasks.push('test') if process.platform is 'darwin' - # ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI - # if process.platform is 'win32' - # ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL - # ciTasks.push('codesign:installer-deferred') if not process.env.JANKY_SIGNTOOL - # ciTasks.push('create-windows-installer:installer') - # ciTasks.push('codesign:installer') if process.env.JANKY_SIGNTOOL - # ciTasks.push('codesign:cleanup') - # ciTasks.push('publish-build') unless process.env.CI + ciTasks.push('dump-symbols') if process.platform is 'darwin' + ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') + ciTasks.push('mkdeb') if process.platform is 'linux' + ciTasks.push('mktar') if process.platform is 'linux' + ciTasks.push('test') if process.platform is 'darwin' + ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI + if process.platform is 'win32' + ciTasks.push('codesign:exe') if process.env.JANKY_SIGNTOOL + ciTasks.push('codesign:installer-deferred') if not process.env.JANKY_SIGNTOOL + ciTasks.push('create-windows-installer:installer') + ciTasks.push('codesign:installer') if process.env.JANKY_SIGNTOOL + ciTasks.push('codesign:cleanup') + ciTasks.push('publish-build') unless process.env.CI grunt.registerTask('ci', ciTasks) From 8d337789001b79b21a4857cfedfccc786a2e22e2 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 13:02:43 +0200 Subject: [PATCH 072/160] Use npm 3.10.5 in build/package.json too --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index d0fd27fe1..533f49417 100644 --- a/build/package.json +++ b/build/package.json @@ -32,7 +32,7 @@ "grunt-standard": "^2.0.0", "legal-eagle": "~0.13.0", "minidump": "~0.9", - "npm": "3.9.5", + "npm": "3.10.5", "rcedit": "~0.3.0", "request": "~2.27.0", "rimraf": "~2.2.2", From 3664c8c2d7d9b9d54c8dc2fe4d9ef930e0a3f62c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 16:04:07 +0200 Subject: [PATCH 073/160] Don't cache electron --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3bdd77f4e..9aa45d0eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,6 @@ cache: - node_modules - apm/node_modules - build/node_modules - - electron notifications: email: From 92483d7369eb2f25f09168f72aab6df9c5329206 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:00:13 +0200 Subject: [PATCH 074/160] Remove the higher timeout --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9aa45d0eb..b17253332 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,6 @@ install: script: script/cibuild cache: - timeout: 1000 directories: - node_modules - apm/node_modules From 54279132cde8cf97318c941a95c0629eb7e2bc40 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 12:38:22 -0400 Subject: [PATCH 075/160] :arrow_up: whitespace@0.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0ab504e9a..3a9e3bd1e 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "tree-view": "0.208.1", "update-package-dependencies": "0.10.0", "welcome": "0.34.0", - "whitespace": "0.32.2", + "whitespace": "0.33.0", "wrap-guide": "0.38.1", "language-c": "0.52.1", "language-clojure": "0.21.0", From 0648e4fce1010cbd6661c645a42cca2ccb214c1c Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Wed, 20 Jul 2016 16:23:51 -0700 Subject: [PATCH 076/160] Run Crash Reporter on both UI & non-UI threads --- src/crash-reporter-start.coffee | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/crash-reporter-start.coffee b/src/crash-reporter-start.coffee index 37c381473..edd7bfd93 100644 --- a/src/crash-reporter-start.coffee +++ b/src/crash-reporter-start.coffee @@ -1,13 +1,9 @@ module.exports = (extra) -> - # Breakpad on Mac OS X must be running on UI and non-UI processes - # Crashpad on Windows and Linux should only be running on non-UI process - return if process.type is 'renderer' and process.platform isnt 'darwin' - {crashReporter} = require 'electron' crashReporter.start({ productName: 'Atom', companyName: 'GitHub', - submitURL: 'http://54.249.141.255:1127/post' + submitURL: 'http://localhost:1127/post' extra: extra }) From 7fa77bc01106fca725d5fbcbfb212db1c3e48b59 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Wed, 20 Jul 2016 16:26:56 -0700 Subject: [PATCH 077/160] Revert Crash Reporter URL endpoint back to correct one --- src/crash-reporter-start.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crash-reporter-start.coffee b/src/crash-reporter-start.coffee index edd7bfd93..af371df79 100644 --- a/src/crash-reporter-start.coffee +++ b/src/crash-reporter-start.coffee @@ -4,6 +4,6 @@ module.exports = (extra) -> crashReporter.start({ productName: 'Atom', companyName: 'GitHub', - submitURL: 'http://localhost:1127/post' + submitURL: 'http://54.249.141.255:1127/post' extra: extra }) From bdda0c0877c395874791d92229854913137e61e4 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:38:53 -0400 Subject: [PATCH 078/160] :arrow_up: language-git@0.15.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a9e3bd1e..410f87759 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "language-csharp": "0.12.1", "language-css": "0.37.0", "language-gfm": "0.88.0", - "language-git": "0.14.0", + "language-git": "0.15.0", "language-go": "0.42.0", "language-html": "0.44.1", "language-hyperlink": "0.16.0", From 9d2c8d4271f2bd470466860963113bb0f6c68c9d Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:40:30 -0400 Subject: [PATCH 079/160] :arrow_up: language-ruby@0.69.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 410f87759..9495b028f 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "language-php": "0.37.1", "language-property-list": "0.8.0", "language-python": "0.45.0", - "language-ruby": "0.68.6", + "language-ruby": "0.69.0", "language-ruby-on-rails": "0.25.0", "language-sass": "0.55.0", "language-shellscript": "0.22.4", From ed06e9536993178d95f2a36489ac44c16b646d84 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:42:35 -0400 Subject: [PATCH 080/160] :arrow_up: language-html@0.45.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9495b028f..e348b99b8 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "language-gfm": "0.88.0", "language-git": "0.15.0", "language-go": "0.42.0", - "language-html": "0.44.1", + "language-html": "0.45.0", "language-hyperlink": "0.16.0", "language-java": "0.23.0", "language-javascript": "0.119.0", From 650608536c3543d2bb0f89691fd78e58bdb03bc0 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:44:35 -0400 Subject: [PATCH 081/160] :arrow_up: language-php@0.37.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e348b99b8..07d6282d0 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "language-mustache": "0.13.0", "language-objective-c": "0.15.1", "language-perl": "0.35.0", - "language-php": "0.37.1", + "language-php": "0.37.2", "language-property-list": "0.8.0", "language-python": "0.45.0", "language-ruby": "0.69.0", From 2da9111bbd692b7ddeae8e0012afa472a4cbaa15 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:45:33 -0400 Subject: [PATCH 082/160] :arrow_up: language-sql@0.23.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 07d6282d0..3d6f4db58 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,7 @@ "language-sass": "0.55.0", "language-shellscript": "0.22.4", "language-source": "0.9.0", - "language-sql": "0.22.0", + "language-sql": "0.23.0", "language-text": "0.7.1", "language-todo": "0.28.0", "language-toml": "0.18.0", From e3ada042a9abc11692ed72a2c5739384af450669 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:46:19 -0400 Subject: [PATCH 083/160] :arrow_up: language-coffee-script@0.47.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d6f4db58..637a56b9f 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "wrap-guide": "0.38.1", "language-c": "0.52.1", "language-clojure": "0.21.0", - "language-coffee-script": "0.47.1", + "language-coffee-script": "0.47.2", "language-csharp": "0.12.1", "language-css": "0.37.0", "language-gfm": "0.88.0", From 28ee230c7b3af0f74e8182783c09c1e887f6dfa3 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:47:10 -0400 Subject: [PATCH 084/160] :arrow_up: language-json@0.18.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 637a56b9f..650bcccec 100644 --- a/package.json +++ b/package.json @@ -133,7 +133,7 @@ "language-hyperlink": "0.16.0", "language-java": "0.23.0", "language-javascript": "0.119.0", - "language-json": "0.18.1", + "language-json": "0.18.2", "language-less": "0.29.4", "language-make": "0.22.2", "language-mustache": "0.13.0", From cad3553115e4c48f076767b003b3e0063c52623c Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:48:19 -0400 Subject: [PATCH 085/160] :arrow_up: language-xml@0.34.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 650bcccec..0eb88679b 100644 --- a/package.json +++ b/package.json @@ -151,7 +151,7 @@ "language-text": "0.7.1", "language-todo": "0.28.0", "language-toml": "0.18.0", - "language-xml": "0.34.8", + "language-xml": "0.34.9", "language-yaml": "0.26.0" }, "private": true, From eeb3aafe4d761c395cb605ccd1e259583d5578ba Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:49:01 -0400 Subject: [PATCH 086/160] :arrow_up: language-sass@0.56.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0eb88679b..7d3426069 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "language-python": "0.45.0", "language-ruby": "0.69.0", "language-ruby-on-rails": "0.25.0", - "language-sass": "0.55.0", + "language-sass": "0.56.0", "language-shellscript": "0.22.4", "language-source": "0.9.0", "language-sql": "0.23.0", From dbc8e99274300f26b9af5f6c16c4bdb5b41f6e29 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:49:54 -0400 Subject: [PATCH 087/160] :arrow_up: language-go@0.42.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d3426069..53ebb989b 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "language-css": "0.37.0", "language-gfm": "0.88.0", "language-git": "0.15.0", - "language-go": "0.42.0", + "language-go": "0.42.1", "language-html": "0.45.0", "language-hyperlink": "0.16.0", "language-java": "0.23.0", From b6759863e0f21c23b6efa63c9c26ac9c45e6ba5e Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:50:44 -0400 Subject: [PATCH 088/160] :arrow_up: language-css@0.37.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 53ebb989b..b2c27ea54 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "language-clojure": "0.21.0", "language-coffee-script": "0.47.2", "language-csharp": "0.12.1", - "language-css": "0.37.0", + "language-css": "0.37.1", "language-gfm": "0.88.0", "language-git": "0.15.0", "language-go": "0.42.1", From 565fe1e8c97603b8556802fbe539bd707ea9908d Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 20 Jul 2016 20:52:06 -0400 Subject: [PATCH 089/160] :arrow_up: language-less@0.29.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2c27ea54..a5af57bb6 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "language-java": "0.23.0", "language-javascript": "0.119.0", "language-json": "0.18.2", - "language-less": "0.29.4", + "language-less": "0.29.5", "language-make": "0.22.2", "language-mustache": "0.13.0", "language-objective-c": "0.15.1", From df08b73f56d34bf64996d7ae04b490885795da3d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Jul 2016 12:33:19 +0200 Subject: [PATCH 090/160] :arrow_up: tabs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a9e3bd1e..0c037cb2d 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "status-bar": "1.4.0", "styleguide": "0.47.0", "symbols-view": "0.113.0", - "tabs": "0.99.0", + "tabs": "0.100.0", "timecop": "0.33.2", "tree-view": "0.208.1", "update-package-dependencies": "0.10.0", From e64fe45cfcd05bccb5f14b45af769ce4d19f1b53 Mon Sep 17 00:00:00 2001 From: Indrek Ardel Date: Thu, 21 Jul 2016 14:49:16 +0300 Subject: [PATCH 091/160] Correctly link the safe mode section --- ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 5b3ea42f4..d2ac45f05 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ ### Prerequisites -* [ ] Can you reproduce the problem in [safe mode](http://flight-manual.atom.io/hacking-atom/sections/debugging/#check-if-the-problem-shows-up-in-safe-mode)? +* [ ] Can you reproduce the problem in [safe mode](http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode)? * [ ] Are you running the [latest version of Atom](http://flight-manual.atom.io/hacking-atom/sections/debugging/#update-to-the-latest-version)? * [ ] Did you check the [debugging guide](http://flight-manual.atom.io/hacking-atom/sections/debugging/)? * [ ] Did you check the [FAQs on Discuss](https://discuss.atom.io/c/faq)? From e2c7f0dab3360cec4862f4eaef3ed6c6314ddaac Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Jul 2016 13:58:33 +0200 Subject: [PATCH 092/160] :arrow_up: apm 1.12.2 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 69aeaa413..3a986dffc 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.12.1" + "atom-package-manager": "1.12.2" } } From 726cc4c077dd1a5915ebe8eef945b1482c68ee02 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 21 Jul 2016 13:42:26 -0600 Subject: [PATCH 093/160] Rename ATOM_REPO to ATOM_PUBLISH_REPO and always publish when it is set --- build/Gruntfile.coffee | 4 +++- build/tasks/publish-build-task.coffee | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index b248eda2e..653e1e268 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -296,7 +296,9 @@ module.exports = (grunt) -> ciTasks.push('create-windows-installer:installer') ciTasks.push('codesign:installer') if process.env.JANKY_SIGNTOOL ciTasks.push('codesign:cleanup') - ciTasks.push('publish-build') unless process.env.CI + + if process.env.ATOM_PUBLISH_REPO or not process.env.CI + ciTasks.push('publish-build') grunt.registerTask('ci', ciTasks) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 2802f827d..27f36aaeb 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -11,7 +11,7 @@ AWS = require 'aws-sdk' grunt = null token = process.env.ATOM_ACCESS_TOKEN -repo = process.env.ATOM_REPO ? 'atom/atom' +repo = process.env.ATOM_PUBLISH_REPO ? 'atom/atom' defaultHeaders = Authorization: "token #{token}" 'User-Agent': 'Atom' From a3b99c51a5d4d9b7e7d79332d1e7a6bc52a1ff25 Mon Sep 17 00:00:00 2001 From: simurai Date: Fri, 22 Jul 2016 21:02:26 +0900 Subject: [PATCH 094/160] :arrow_up: one-light-ui@v1.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0580923af..246560d42 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "base16-tomorrow-dark-theme": "1.1.0", "base16-tomorrow-light-theme": "1.1.1", "one-dark-ui": "1.4.0", - "one-light-ui": "1.4.0", + "one-light-ui": "1.5.0", "one-dark-syntax": "1.3.0", "one-light-syntax": "1.3.0", "solarized-dark-syntax": "1.0.2", From e92e2c061d8b33f7eb522da427e0425b24b37391 Mon Sep 17 00:00:00 2001 From: simurai Date: Fri, 22 Jul 2016 21:03:11 +0900 Subject: [PATCH 095/160] :arrow_up: one-dark-ui@v1.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 246560d42..717c0e00d 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "atom-light-ui": "0.44.0", "base16-tomorrow-dark-theme": "1.1.0", "base16-tomorrow-light-theme": "1.1.1", - "one-dark-ui": "1.4.0", + "one-dark-ui": "1.5.0", "one-light-ui": "1.5.0", "one-dark-syntax": "1.3.0", "one-light-syntax": "1.3.0", From 18271ec8cc601b6abcf5d7efdbd34680ba955d22 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Jul 2016 18:04:05 +0200 Subject: [PATCH 096/160] :arrow_up: apm 1.12.3 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 3a986dffc..18f313c16 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.12.2" + "atom-package-manager": "1.12.3" } } From 2a369aa5673ea346f52a776253a4e80cf731d767 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 21 Jul 2016 17:13:18 -0600 Subject: [PATCH 097/160] =?UTF-8?q?Don=E2=80=99t=20clobber=20S3=20creds=20?= =?UTF-8?q?on=20Windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/cibuild | 4 ---- 1 file changed, 4 deletions(-) diff --git a/script/cibuild b/script/cibuild index 627c2291a..6f16ac5cd 100755 --- a/script/cibuild +++ b/script/cibuild @@ -40,10 +40,6 @@ function setEnvironmentVariables() { process.env.CC = 'clang'; process.env.CXX = 'clang++'; process.env.npm_config_clang = '1'; - } else if (process.platform === 'win32') { - process.env.BUILD_ATOM_RELEASES_S3_KEY = process.env.BUILD_ATOM_WIN_RELEASES_S3_KEY - process.env.BUILD_ATOM_RELEASES_S3_SECRET = process.env.BUILD_ATOM_WIN_RELEASES_S3_SECRET - process.env.BUILD_ATOM_RELEASES_S3_BUCKET = process.env.BUILD_ATOM_WIN_RELEASES_S3_BUCKET } } From f7a4b8f33f931ab10909a2429c9a0876b637e11f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 21 Jul 2016 17:16:58 -0600 Subject: [PATCH 098/160] Build more than master on appveyor --- appveyor.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 51e074a4c..56335e8bd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,5 @@ version: "{build}" -branches: - only: - - master - skip_tags: true clone_folder: c:\projects\atom clone_depth: 10 From c65d45ea62426a63927913a92bb811542ba39e23 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Thu, 21 Jul 2016 16:59:49 -0700 Subject: [PATCH 099/160] Add logging to publish-build-task --- build/tasks/publish-build-task.coffee | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 27f36aaeb..1d5322d61 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -119,6 +119,7 @@ logError = (message, error, details) -> zipAssets = (buildDir, assets, callback) -> zip = (directory, sourcePath, assetName, callback) -> + grunt.log.ok("Zipping #{sourcePath} into #{assetName}") if process.platform is 'win32' sevenZipPath = if process.env.JANKY_SHA1? then "C:/psmodules/" else "" zipCommand = "#{sevenZipPath}7z.exe a -r \"#{assetName}\" \"#{sourcePath}\"" @@ -136,6 +137,7 @@ zipAssets = (buildDir, assets, callback) -> async.parallel(tasks, callback) getAtomDraftRelease = (isPrerelease, branchName, callback) -> + grunt.log.ok("Obtaining GitHub draft release for #{branchName}") atomRepo = new GitHub({repo: repo, token}) atomRepo.getReleases {prerelease: isPrerelease}, (error, releases=[]) -> if error? @@ -154,12 +156,14 @@ getAtomDraftRelease = (isPrerelease, branchName, callback) -> logError('Fetching draft release assets failed', error, assets) callback(error ? new Error(response.statusCode)) else + grunt.log.ok("Using GitHub draft release #{firstDraft.name}") firstDraft.assets = assets callback(null, firstDraft) else createAtomDraftRelease(isPrerelease, branchName, callback) createAtomDraftRelease = (isPrerelease, branchName, callback) -> + grunt.log.ok("Creating GitHub draft release #{branchName}") {version} = require('../../package.json') options = uri: "https://api.github.com/repos/#{repo}/releases" @@ -185,6 +189,7 @@ createAtomDraftRelease = (isPrerelease, branchName, callback) -> callback(null, body) deleteRelease = (release) -> + grunt.log.ok("Deleting GitHub release #{release}") options = uri: release.url method: 'DELETE' @@ -195,6 +200,7 @@ deleteRelease = (release) -> logError('Deleting release failed', error, body) deleteExistingAssets = (release, assetNames, callback) -> + grunt.log.ok("Deleting #{assetNames.join(',')} from GitHub release #{release}") [callback, assetNames] = [assetNames, callback] if not callback? deleteAsset = (url, callback) -> @@ -216,6 +222,7 @@ deleteExistingAssets = (release, assetNames, callback) -> uploadAssets = (release, buildDir, assets, callback) -> uploadToReleases = (release, assetName, assetPath, callback) -> + grunt.log.ok("Uploading #{assetName} to GitHub release #{release}") options = uri: release.upload_url.replace(/\{.*$/, "?name=#{assetName}") method: 'POST' @@ -248,6 +255,7 @@ uploadAssets = (release, buildDir, assets, callback) -> s3 = new AWS.S3 s3Info key = "releases/#{release.tag_name}/#{assetName}" + grunt.log.ok("Uploading to S3 #{key}") uploadParams = Bucket: s3Bucket ACL: 'public-read' From e60b5f8542f1cc55040cd122518ed2810d5993bf Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Jul 2016 09:53:58 -0600 Subject: [PATCH 100/160] Cache node_modules on AppVeyor Signed-off-by: Antonio Scandurra --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 56335e8bd..6248db85e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,6 +33,9 @@ artifacts: name: AtomSetup.msi cache: + - '%APPVEYOR_BUILD_FOLDER%\build\node_modules' + - '%APPVEYOR_BUILD_FOLDER%\apm\node_modules' + - '%APPVEYOR_BUILD_FOLDER%\node_modules' - '%USERPROFILE%\.atom\.apm' - '%USERPROFILE%\.atom\.node-gyp\.atom' - '%USERPROFILE%\.atom\.npm' From 6afb4da0cf0efe9814418e0e5bbbf65d797d2a14 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Fri, 22 Jul 2016 09:32:41 -0700 Subject: [PATCH 101/160] Add repo logging to publish task --- build/tasks/publish-build-task.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 1d5322d61..e4b372b36 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -32,6 +32,7 @@ module.exports = (gruntObject) -> cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json') grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', -> + grunt.log.ok("Starting upload-assets to #{repo} repo") releaseBranch = grunt.config.get('atom.releaseBranch') isPrerelease = grunt.config.get('atom.channel') is 'beta' return unless releaseBranch? From 24feb64a52b0e32cd5e220ca480f6e34be590cfd Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Jul 2016 16:01:07 -0600 Subject: [PATCH 102/160] Log release.tag_name correctly --- build/tasks/publish-build-task.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index e4b372b36..1cc90eae4 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -190,7 +190,7 @@ createAtomDraftRelease = (isPrerelease, branchName, callback) -> callback(null, body) deleteRelease = (release) -> - grunt.log.ok("Deleting GitHub release #{release}") + grunt.log.ok("Deleting GitHub release #{release.tag_name}") options = uri: release.url method: 'DELETE' @@ -201,7 +201,7 @@ deleteRelease = (release) -> logError('Deleting release failed', error, body) deleteExistingAssets = (release, assetNames, callback) -> - grunt.log.ok("Deleting #{assetNames.join(',')} from GitHub release #{release}") + grunt.log.ok("Deleting #{assetNames.join(',')} from GitHub release #{release.tag_name}") [callback, assetNames] = [assetNames, callback] if not callback? deleteAsset = (url, callback) -> @@ -223,7 +223,7 @@ deleteExistingAssets = (release, assetNames, callback) -> uploadAssets = (release, buildDir, assets, callback) -> uploadToReleases = (release, assetName, assetPath, callback) -> - grunt.log.ok("Uploading #{assetName} to GitHub release #{release}") + grunt.log.ok("Uploading #{assetName} to GitHub release #{release.tag_name}") options = uri: release.upload_url.replace(/\{.*$/, "?name=#{assetName}") method: 'POST' From 1c3bd102cac22910992ff3da8e5a958734838166 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Jul 2016 16:04:53 -0600 Subject: [PATCH 103/160] Clarify logging when upload-assets is skipped on non-release branches --- build/tasks/publish-build-task.coffee | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 1cc90eae4..ad31c0d8e 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -32,10 +32,14 @@ module.exports = (gruntObject) -> cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json') grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', -> - grunt.log.ok("Starting upload-assets to #{repo} repo") releaseBranch = grunt.config.get('atom.releaseBranch') isPrerelease = grunt.config.get('atom.channel') is 'beta' - return unless releaseBranch? + + unless releaseBranch? + grunt.log.ok("Skipping upload-assets to #{repo} repo because this is not a release branch") + return + + grunt.log.ok("Starting upload-assets to #{repo} repo") doneCallback = @async() startTime = Date.now() From 71e7d3291649387a32d421dbfbdbaf76af838b76 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Mon, 25 Jul 2016 07:49:04 +0900 Subject: [PATCH 104/160] :racehorse: Transact setSchema config changes --- src/config.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 27ea1edef..c334cc1ec 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -786,9 +786,10 @@ class Config rootSchema = properties[key] Object.assign rootSchema, schema - @setDefaults(keyPath, @extractDefaultsFromSchema(schema)) - @setScopedDefaultsFromSchema(keyPath, schema) - @resetSettingsForSchemaChange() + @transact => + @setDefaults(keyPath, @extractDefaultsFromSchema(schema)) + @setScopedDefaultsFromSchema(keyPath, schema) + @resetSettingsForSchemaChange() load: -> @initializeConfigDirectory() From b66d1acb025d180fdc75bba6c15719fd0183b2c0 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Mon, 25 Jul 2016 07:51:11 +0900 Subject: [PATCH 105/160] :racehorse: Skip require from settings view if configSchema --- src/package.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/package.coffee b/src/package.coffee index b27e3ce0e..1bb8a939c 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -159,6 +159,7 @@ class Package # TODO: Remove. Settings view calls this method currently. activateConfig: -> + return if @configSchemaRegisteredOnLoad @requireMainModule() @registerConfigSchemaFromMainModule() From 9199b7ffa99d442c8b0729f0dc1724fdc26ddfea Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Mon, 25 Jul 2016 09:22:25 -0700 Subject: [PATCH 106/160] Disable autosubmit of crash reporter --- src/crash-reporter-start.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crash-reporter-start.coffee b/src/crash-reporter-start.coffee index af371df79..f19e61179 100644 --- a/src/crash-reporter-start.coffee +++ b/src/crash-reporter-start.coffee @@ -4,6 +4,6 @@ module.exports = (extra) -> crashReporter.start({ productName: 'Atom', companyName: 'GitHub', - submitURL: 'http://54.249.141.255:1127/post' + autoSubmit: false, extra: extra }) From 3589d6173ff4115ccba92428f175fe39dc2d8ddd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:22:24 +0200 Subject: [PATCH 107/160] Start on Circle CI --- circle.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index a55900cca..d43f769c6 100644 --- a/circle.yml +++ b/circle.yml @@ -1,4 +1,16 @@ +machine: + node: + version: 4.4.7 + general: branches: only: - - io-circle-ci + - as-circle-ci + +dependencies: + override: + - script/bootstrap + +test: + override: + - script/grunt ci From d2d9ddacd86142ad9ed7be134793dbf8e657599e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:26:13 +0200 Subject: [PATCH 108/160] Use the latest Xcode --- circle.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/circle.yml b/circle.yml index d43f769c6..2b7f64496 100644 --- a/circle.yml +++ b/circle.yml @@ -1,4 +1,7 @@ machine: + xcode: + version: 7.3 + node: version: 4.4.7 From 0fa6119df8e821c35933e8a5eff0946c656c5be6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:28:36 +0200 Subject: [PATCH 109/160] Try skipping xcode_scheme --- circle.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/circle.yml b/circle.yml index 2b7f64496..c8ff35153 100644 --- a/circle.yml +++ b/circle.yml @@ -1,4 +1,7 @@ machine: + environment: + XCODE_SCHEME: test + xcode: version: 7.3 From 4f64abc0898eec0d3fbba40c8f5199adaaad74d4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:37:29 +0200 Subject: [PATCH 110/160] Test --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index c8ff35153..1570fbfd2 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,7 @@ machine: environment: XCODE_SCHEME: test + XCODE_WORKSPACE: test xcode: version: 7.3 From e8d25250cc8f7ccaf52fb18ede77b915176ddf13 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:39:43 +0200 Subject: [PATCH 111/160] Another test --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index 1570fbfd2..381b81241 100644 --- a/circle.yml +++ b/circle.yml @@ -2,6 +2,7 @@ machine: environment: XCODE_SCHEME: test XCODE_WORKSPACE: test + XCODE_PROJECT: test xcode: version: 7.3 From 9204238c243830143cb36144af3c25d992e83b35 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:41:21 +0200 Subject: [PATCH 112/160] Install node via nvm --- circle.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/circle.yml b/circle.yml index 381b81241..e30bd9db7 100644 --- a/circle.yml +++ b/circle.yml @@ -7,15 +7,17 @@ machine: xcode: version: 7.3 - node: - version: 4.4.7 - general: branches: only: - as-circle-ci dependencies: + pre: + - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash + - nvm install 4.4.7 + - nvm use 4.4.7 + override: - script/bootstrap From 77f8811b187855c15e87fbc55137332a95ab6a92 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 18:43:15 +0200 Subject: [PATCH 113/160] Upgrade npm before running script/bootstrap --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index e30bd9db7..40cf6c478 100644 --- a/circle.yml +++ b/circle.yml @@ -17,6 +17,7 @@ dependencies: - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash - nvm install 4.4.7 - nvm use 4.4.7 + - npm install -g npm override: - script/bootstrap From 1e00a9ad2736721d8663ff963916cba37154ca2d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 19:07:06 +0200 Subject: [PATCH 114/160] Cache node_modules on CircleCI --- circle.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/circle.yml b/circle.yml index 40cf6c478..28225cd11 100644 --- a/circle.yml +++ b/circle.yml @@ -22,6 +22,12 @@ dependencies: override: - script/bootstrap + cache_directories: + - apm/node_modules + - build/node_modules + - node_modules + - electron + test: override: - script/grunt ci From ea969d71ec1d479d1d7fd5be52dbb0236d789113 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 19:33:34 +0200 Subject: [PATCH 115/160] Use fingerprint to invalidate cache --- circle.yml | 4 ++++ script/fingerprint-clean | 23 +++++++++++++++++++++++ script/fingerprint-write | 2 ++ 3 files changed, 29 insertions(+) create mode 100755 script/fingerprint-clean create mode 100755 script/fingerprint-write diff --git a/circle.yml b/circle.yml index 28225cd11..3f3b86c07 100644 --- a/circle.yml +++ b/circle.yml @@ -18,10 +18,14 @@ dependencies: - nvm install 4.4.7 - nvm use 4.4.7 - npm install -g npm + - script/fingerprint-clean override: - script/bootstrap + post: + - script/fingerprint-write + cache_directories: - apm/node_modules - build/node_modules diff --git a/script/fingerprint-clean b/script/fingerprint-clean new file mode 100755 index 000000000..6c2a67ca0 --- /dev/null +++ b/script/fingerprint-clean @@ -0,0 +1,23 @@ +#!/usr/bin/env node +var fingerprint = require('./utils/fingerprint') + +if (fingerprint.fingerprintMatches()) { + console.log('node_modules matches current fingerprint ' + fingerprint.fingerprint() + ' - not removing') + return +} + +var fsPlus +try { + fsPlus = require('fs-plus') +} catch (error) { + console.log(error.message) + return +} + +try { + fsPlus.removeSync(path.resolve(__dirname, '..', 'node_modules')) + fsPlus.removeSync(path.resolve(__dirname, '..', 'apm', 'node_modules')) +} catch (error) { + console.error(error.message) + process.exit(1) +} diff --git a/script/fingerprint-write b/script/fingerprint-write new file mode 100755 index 000000000..e5fad4d72 --- /dev/null +++ b/script/fingerprint-write @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./utils/fingerprint').writeFingerprint() From 8c4b836558e3f239a48d30d536d9f761e5a30928 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 20:28:33 +0200 Subject: [PATCH 116/160] :fire: Remove Electron from cache --- circle.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/circle.yml b/circle.yml index 3f3b86c07..a5efd757f 100644 --- a/circle.yml +++ b/circle.yml @@ -30,7 +30,6 @@ dependencies: - apm/node_modules - build/node_modules - node_modules - - electron test: override: From ee32342230cc083eb91fab009fb51574d7f3b2c6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Jul 2016 20:33:21 +0200 Subject: [PATCH 117/160] Don't remove node_modules if we don't have a fingerprint --- script/fingerprint-clean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/script/fingerprint-clean b/script/fingerprint-clean index 6c2a67ca0..659395190 100755 --- a/script/fingerprint-clean +++ b/script/fingerprint-clean @@ -1,5 +1,11 @@ #!/usr/bin/env node var fingerprint = require('./utils/fingerprint') +var fs = require('fs') +var path = require('path') + +if (!fs.existsSync(path.resolve(__dirname, '..', 'node_modules', '.atom-ci-fingerprint'))) { + return +} if (fingerprint.fingerprintMatches()) { console.log('node_modules matches current fingerprint ' + fingerprint.fingerprint() + ' - not removing') From a06ff650ee4233ad513abb2beb9dd3e1a91ce81f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Jul 2016 11:07:43 +0200 Subject: [PATCH 118/160] Build all the branches --- circle.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/circle.yml b/circle.yml index a5efd757f..86e5cbdae 100644 --- a/circle.yml +++ b/circle.yml @@ -7,11 +7,6 @@ machine: xcode: version: 7.3 -general: - branches: - only: - - as-circle-ci - dependencies: pre: - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash From 919be72ce7aa2fd339584734d4755efa92707101 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Jul 2016 11:09:04 +0200 Subject: [PATCH 119/160] Make Atom.app downloadable from the artifacts --- circle.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/circle.yml b/circle.yml index 86e5cbdae..313515b5a 100644 --- a/circle.yml +++ b/circle.yml @@ -7,6 +7,10 @@ machine: xcode: version: 7.3 +general: + artifacts: + - out/Atom.app + dependencies: pre: - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash From 5a4be54b5622b2127444e3b2ec2d5993d304c5c3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Jul 2016 11:43:46 +0200 Subject: [PATCH 120/160] Zip before collecting artifact --- circle.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 313515b5a..95ebb024c 100644 --- a/circle.yml +++ b/circle.yml @@ -9,7 +9,7 @@ machine: general: artifacts: - - out/Atom.app + - out/Atom.zip dependencies: pre: @@ -33,3 +33,6 @@ dependencies: test: override: - script/grunt ci + + post: + - zip -r out/Atom.zip out/Atom.app From 64c5924b3fdceab627a8161df90d066b1a519b2e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Jul 2016 18:09:15 +0200 Subject: [PATCH 121/160] Replace Travis status badge with CircleCI Signed-off-by: Nathan Sobo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f052ccff..55d93aff7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png) -[![macOS Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) +[![macOS Build Status](https://circleci.com/gh/atom/atom.svg?style=svg)](https://circleci.com/gh/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) [![Join the Atom Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) From ca09bdf1951a7e12fabfeacf9ee1ac4081eeed44 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 25 Jul 2016 19:00:47 +0200 Subject: [PATCH 122/160] Remove OS X from Travis Build Matrix Signed-off-by: Nathan Sobo --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index b17253332..9ac8cc72a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,18 +9,12 @@ env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 -osx_image: xcode7.3 - compiler: clang matrix: include: - os: linux env: NODE_VERSION=4 - - os: osx - env: ATOM_SPECS_TASK=core NODE_VERSION=4 - - os: osx - env: ATOM_SPECS_TASK=packages NODE_VERSION=4 sudo: false From f19e043f5c689c73416bbd54cc4b9bac4ea358de Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 25 Jul 2016 16:22:22 -0600 Subject: [PATCH 123/160] Revert "Use apm@1.12.2 with Node v4 and npm v3 \o/" --- .travis.yml | 16 +++++++--------- Dockerfile | 8 +++++--- apm/package.json | 2 +- appveyor.yml | 3 +-- build/package.json | 2 +- build/tasks/compile-packages-slug-task.coffee | 2 -- script/bootstrap | 9 +++++++-- script/cibuild-atom-linux | 11 +++++------ script/utils/fingerprint.js | 8 +++----- 9 files changed, 30 insertions(+), 31 deletions(-) diff --git a/.travis.yml b/.travis.yml index b17253332..7b6113aa0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,18 +9,18 @@ env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 -osx_image: xcode7.3 - compiler: clang matrix: include: + - os: linux + env: NODE_VERSION=0.12 - os: linux env: NODE_VERSION=4 - os: osx - env: ATOM_SPECS_TASK=core NODE_VERSION=4 + env: ATOM_SPECS_TASK=core NODE_VERSION=0.12 - os: osx - env: ATOM_SPECS_TASK=packages NODE_VERSION=4 + env: ATOM_SPECS_TASK=packages NODE_VERSION=0.12 sudo: false @@ -28,15 +28,16 @@ install: - git clone https://github.com/creationix/nvm.git /tmp/.nvm - source /tmp/.nvm/nvm.sh - nvm install $NODE_VERSION - - nvm use --delete-prefix $NODE_VERSION + - nvm use $NODE_VERSION script: script/cibuild cache: directories: - node_modules - - apm/node_modules - build/node_modules + - apm/node_modules + - $HOME/.atom/compile-cache notifications: email: @@ -45,11 +46,8 @@ notifications: addons: apt: - sources: - - ubuntu-toolchain-r-test packages: - build-essential - git - libgnome-keyring-dev - fakeroot - - gcc-multilib diff --git a/Dockerfile b/Dockerfile index 22a101743..d792c30c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # DESCRIPTION: Image to build Atom and create a .rpm file # Base docker image -FROM nodesource/fedora21:4.2.6 +FROM fedora:21 # Install dependencies RUN yum install -y \ @@ -12,9 +12,11 @@ RUN yum install -y \ glibc-devel \ git-core \ libgnome-keyring-devel \ - rpmdevtools + rpmdevtools \ + nodejs \ + npm -RUN npm install -g npm --loglevel error +RUN npm install -g npm@1.4.28 --loglevel error ADD . /atom WORKDIR /atom diff --git a/apm/package.json b/apm/package.json index 18f313c16..d4fcc851a 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.12.3" + "atom-package-manager": "1.10.0" } } diff --git a/appveyor.yml b/appveyor.yml index 316701aae..6248db85e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,10 +12,9 @@ environment: ATOM_DEV_RESOURCE_PATH: c:\projects\atom ATOM_ACCESS_TOKEN: secure: Q7vxmSq0bVCLTTRPzXw5ZhPTe7XYhWxX0tQV6neEkddTH6pZkOYNmSCG6VnMX2f+ - ATOM_NOISY_BUILD: 1 matrix: - - NODE_VERSION: 4.4.5 + - NODE_VERSION: 0.10.35 install: - SET PATH=C:\Program Files\Atom\resources\cli;%PATH% diff --git a/build/package.json b/build/package.json index 533f49417..2f8d88d8a 100644 --- a/build/package.json +++ b/build/package.json @@ -32,7 +32,7 @@ "grunt-standard": "^2.0.0", "legal-eagle": "~0.13.0", "minidump": "~0.9", - "npm": "3.10.5", + "npm": "2.13.3", "rcedit": "~0.3.0", "request": "~2.27.0", "rimraf": "~2.2.2", diff --git a/build/tasks/compile-packages-slug-task.coffee b/build/tasks/compile-packages-slug-task.coffee index f6f297bec..7317f158a 100644 --- a/build/tasks/compile-packages-slug-task.coffee +++ b/build/tasks/compile-packages-slug-task.coffee @@ -40,8 +40,6 @@ module.exports = (grunt) -> continue if path.basename(moduleDirectory) is '.bin' metadataPath = path.join(moduleDirectory, 'package.json') - continue unless fs.existsSync(metadataPath) - metadata = grunt.file.readJSON(metadataPath) continue unless metadata?.engines?.atom? diff --git a/script/bootstrap b/script/bootstrap index 6fcf8fef0..3b9a35735 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -75,7 +75,7 @@ function bootstrap() { var buildInstallCommand = initialNpmCommand + npmFlags + 'install'; var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')}; - var apmInstallCommand = npmPath + npmFlags + '--target=4.4.5 --global-style ' + 'install'; + var apmInstallCommand = npmPath + npmFlags + '--target=0.10.40 ' + 'install'; var apmInstallOptions = {cwd: apmInstallPath}; var moduleInstallCommand = apmPath + ' install' + apmFlags; var dedupeApmCommand = apmPath + ' dedupe' + apmFlags; @@ -97,7 +97,7 @@ function bootstrap() { } var moduleInstallOptions = {env: moduleInstallEnv}; - if (process.argv.indexOf('--no-quiet') === -1 || process.env.ATOM_NOISY_BUILD) { + if (process.argv.indexOf('--no-quiet') === -1) { buildInstallCommand += ' --loglevel error'; apmInstallCommand += ' --loglevel error'; moduleInstallCommand += ' --loglevel error'; @@ -122,6 +122,11 @@ function bootstrap() { message: 'Installing apm...', options: apmInstallOptions }, + { + command: apmPath + ' clean' + apmFlags, + message: 'Deleting old packages...', + options: moduleInstallOptions + }, { command: moduleInstallCommand, options: moduleInstallOptions diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index fe79c19fe..2c3395608 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -7,11 +7,10 @@ export BUILD_ATOM_RELEASES_S3_KEY=$BUILD_ATOM_LINUX_RELEASES_S3_KEY export BUILD_ATOM_RELEASES_S3_SECRET=$BUILD_ATOM_LINUX_RELEASES_S3_SECRET export BUILD_ATOM_RELEASES_S3_BUCKET=$BUILD_ATOM_LINUX_RELEASES_S3_BUCKET -rm -rf /tmp/.atom-nvm -git clone https://github.com/creationix/nvm.git /tmp/.atom-nvm -source /tmp/.atom-nvm/nvm.sh -nvm install 4.4.7 -nvm use 4.4.7 -npm install -g npm +if [ -d /usr/local/share/nodenv ]; then + export NODENV_ROOT=/usr/local/share/nodenv + export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH + export NODENV_VERSION="v0.10.21" +fi script/cibuild diff --git a/script/utils/fingerprint.js b/script/utils/fingerprint.js index e1f6276d2..c419ba4fd 100644 --- a/script/utils/fingerprint.js +++ b/script/utils/fingerprint.js @@ -6,14 +6,12 @@ var fingerprintPath = path.resolve(__dirname, '..', '..', 'node_modules', '.atom module.exports = { fingerprint: function () { - var atomPackageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) - var apmPackageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'apm', 'package.json')) + var packageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) //Include the electron minor version in the fingerprint since that changing requires a re-install - var electronVersion = JSON.parse(atomPackageJson).electronVersion.replace(/\.\d+$/, '') - var apmVersion = JSON.parse(apmPackageJson).dependencies['atom-package-manager'] + var electronVersion = JSON.parse(packageJson).electronVersion.replace(/\.\d+$/, '') - var body = electronVersion + apmVersion + process.platform + process.version + var body = electronVersion + process.platform + process.version return crypto.createHash('sha1').update(body).digest('hex') }, From 8550fe028b407c1744275a88b2ac3ef1bd51d0cb Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Tue, 26 Jul 2016 09:10:43 -0700 Subject: [PATCH 124/160] New crashreporter URL to prevent warnings --- src/crash-reporter-start.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crash-reporter-start.coffee b/src/crash-reporter-start.coffee index f19e61179..47aae2469 100644 --- a/src/crash-reporter-start.coffee +++ b/src/crash-reporter-start.coffee @@ -4,6 +4,7 @@ module.exports = (extra) -> crashReporter.start({ productName: 'Atom', companyName: 'GitHub', + submitURL: 'https://crashreporter.atom.io', autoSubmit: false, extra: extra }) From beeeaeb5214e9a3d94f3d9798c69bed1dd1c50ea Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Jul 2016 10:29:25 -0600 Subject: [PATCH 125/160] Revert "Revert "Use apm@1.12.2 with Node v4 and npm v3 \o/"" --- .travis.yml | 16 +++++++++------- Dockerfile | 8 +++----- apm/package.json | 2 +- appveyor.yml | 3 ++- build/package.json | 2 +- build/tasks/compile-packages-slug-task.coffee | 2 ++ script/bootstrap | 9 ++------- script/cibuild-atom-linux | 11 ++++++----- script/utils/fingerprint.js | 8 +++++--- 9 files changed, 31 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b6113aa0..b17253332 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,18 +9,18 @@ env: global: - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 +osx_image: xcode7.3 + compiler: clang matrix: include: - - os: linux - env: NODE_VERSION=0.12 - os: linux env: NODE_VERSION=4 - os: osx - env: ATOM_SPECS_TASK=core NODE_VERSION=0.12 + env: ATOM_SPECS_TASK=core NODE_VERSION=4 - os: osx - env: ATOM_SPECS_TASK=packages NODE_VERSION=0.12 + env: ATOM_SPECS_TASK=packages NODE_VERSION=4 sudo: false @@ -28,16 +28,15 @@ install: - git clone https://github.com/creationix/nvm.git /tmp/.nvm - source /tmp/.nvm/nvm.sh - nvm install $NODE_VERSION - - nvm use $NODE_VERSION + - nvm use --delete-prefix $NODE_VERSION script: script/cibuild cache: directories: - node_modules - - build/node_modules - apm/node_modules - - $HOME/.atom/compile-cache + - build/node_modules notifications: email: @@ -46,8 +45,11 @@ notifications: addons: apt: + sources: + - ubuntu-toolchain-r-test packages: - build-essential - git - libgnome-keyring-dev - fakeroot + - gcc-multilib diff --git a/Dockerfile b/Dockerfile index d792c30c5..22a101743 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # DESCRIPTION: Image to build Atom and create a .rpm file # Base docker image -FROM fedora:21 +FROM nodesource/fedora21:4.2.6 # Install dependencies RUN yum install -y \ @@ -12,11 +12,9 @@ RUN yum install -y \ glibc-devel \ git-core \ libgnome-keyring-devel \ - rpmdevtools \ - nodejs \ - npm + rpmdevtools -RUN npm install -g npm@1.4.28 --loglevel error +RUN npm install -g npm --loglevel error ADD . /atom WORKDIR /atom diff --git a/apm/package.json b/apm/package.json index d4fcc851a..18f313c16 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.10.0" + "atom-package-manager": "1.12.3" } } diff --git a/appveyor.yml b/appveyor.yml index 6248db85e..316701aae 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,9 +12,10 @@ environment: ATOM_DEV_RESOURCE_PATH: c:\projects\atom ATOM_ACCESS_TOKEN: secure: Q7vxmSq0bVCLTTRPzXw5ZhPTe7XYhWxX0tQV6neEkddTH6pZkOYNmSCG6VnMX2f+ + ATOM_NOISY_BUILD: 1 matrix: - - NODE_VERSION: 0.10.35 + - NODE_VERSION: 4.4.5 install: - SET PATH=C:\Program Files\Atom\resources\cli;%PATH% diff --git a/build/package.json b/build/package.json index 2f8d88d8a..533f49417 100644 --- a/build/package.json +++ b/build/package.json @@ -32,7 +32,7 @@ "grunt-standard": "^2.0.0", "legal-eagle": "~0.13.0", "minidump": "~0.9", - "npm": "2.13.3", + "npm": "3.10.5", "rcedit": "~0.3.0", "request": "~2.27.0", "rimraf": "~2.2.2", diff --git a/build/tasks/compile-packages-slug-task.coffee b/build/tasks/compile-packages-slug-task.coffee index 7317f158a..f6f297bec 100644 --- a/build/tasks/compile-packages-slug-task.coffee +++ b/build/tasks/compile-packages-slug-task.coffee @@ -40,6 +40,8 @@ module.exports = (grunt) -> continue if path.basename(moduleDirectory) is '.bin' metadataPath = path.join(moduleDirectory, 'package.json') + continue unless fs.existsSync(metadataPath) + metadata = grunt.file.readJSON(metadataPath) continue unless metadata?.engines?.atom? diff --git a/script/bootstrap b/script/bootstrap index 3b9a35735..6fcf8fef0 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -75,7 +75,7 @@ function bootstrap() { var buildInstallCommand = initialNpmCommand + npmFlags + 'install'; var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')}; - var apmInstallCommand = npmPath + npmFlags + '--target=0.10.40 ' + 'install'; + var apmInstallCommand = npmPath + npmFlags + '--target=4.4.5 --global-style ' + 'install'; var apmInstallOptions = {cwd: apmInstallPath}; var moduleInstallCommand = apmPath + ' install' + apmFlags; var dedupeApmCommand = apmPath + ' dedupe' + apmFlags; @@ -97,7 +97,7 @@ function bootstrap() { } var moduleInstallOptions = {env: moduleInstallEnv}; - if (process.argv.indexOf('--no-quiet') === -1) { + if (process.argv.indexOf('--no-quiet') === -1 || process.env.ATOM_NOISY_BUILD) { buildInstallCommand += ' --loglevel error'; apmInstallCommand += ' --loglevel error'; moduleInstallCommand += ' --loglevel error'; @@ -122,11 +122,6 @@ function bootstrap() { message: 'Installing apm...', options: apmInstallOptions }, - { - command: apmPath + ' clean' + apmFlags, - message: 'Deleting old packages...', - options: moduleInstallOptions - }, { command: moduleInstallCommand, options: moduleInstallOptions diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index 2c3395608..fe79c19fe 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -7,10 +7,11 @@ export BUILD_ATOM_RELEASES_S3_KEY=$BUILD_ATOM_LINUX_RELEASES_S3_KEY export BUILD_ATOM_RELEASES_S3_SECRET=$BUILD_ATOM_LINUX_RELEASES_S3_SECRET export BUILD_ATOM_RELEASES_S3_BUCKET=$BUILD_ATOM_LINUX_RELEASES_S3_BUCKET -if [ -d /usr/local/share/nodenv ]; then - export NODENV_ROOT=/usr/local/share/nodenv - export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH - export NODENV_VERSION="v0.10.21" -fi +rm -rf /tmp/.atom-nvm +git clone https://github.com/creationix/nvm.git /tmp/.atom-nvm +source /tmp/.atom-nvm/nvm.sh +nvm install 4.4.7 +nvm use 4.4.7 +npm install -g npm script/cibuild diff --git a/script/utils/fingerprint.js b/script/utils/fingerprint.js index c419ba4fd..e1f6276d2 100644 --- a/script/utils/fingerprint.js +++ b/script/utils/fingerprint.js @@ -6,12 +6,14 @@ var fingerprintPath = path.resolve(__dirname, '..', '..', 'node_modules', '.atom module.exports = { fingerprint: function () { - var packageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) + var atomPackageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) + var apmPackageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'apm', 'package.json')) //Include the electron minor version in the fingerprint since that changing requires a re-install - var electronVersion = JSON.parse(packageJson).electronVersion.replace(/\.\d+$/, '') + var electronVersion = JSON.parse(atomPackageJson).electronVersion.replace(/\.\d+$/, '') + var apmVersion = JSON.parse(apmPackageJson).dependencies['atom-package-manager'] - var body = electronVersion + process.platform + process.version + var body = electronVersion + apmVersion + process.platform + process.version return crypto.createHash('sha1').update(body).digest('hex') }, From ea8ca2f17fdbb21c9d94150ac375a4f70dfcff67 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Jul 2016 10:31:21 -0600 Subject: [PATCH 126/160] :arrow_up: atom-package-manager to fix asar-require issues --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 18f313c16..31162dcaf 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.12.3" + "atom-package-manager": "1.12.5" } } From 8b259a9f9f3883642bae2dbeeb07d395340e99e7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 10:29:37 +0200 Subject: [PATCH 127/160] Put back Travis badge for Linux build status --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 55d93aff7..a41ddeb64 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png) -[![macOS Build Status](https://circleci.com/gh/atom/atom.svg?style=svg)](https://circleci.com/gh/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) +[![macOS Build Status](https://circleci.com/gh/atom/atom.svg?style=svg)](https://circleci.com/gh/atom/atom) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) [![Join the Atom Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) From 1d2f9cfeef46e86d6e5f607bdc148050480660e5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 11:02:23 +0200 Subject: [PATCH 128/160] Make sure script/grunt exports ATOM_RESOURCE_PATH --- script/grunt | 1 + 1 file changed, 1 insertion(+) diff --git a/script/grunt b/script/grunt index 99f6860d2..50f5930fa 100755 --- a/script/grunt +++ b/script/grunt @@ -1,4 +1,5 @@ #!/usr/bin/env node +process.env.ATOM_RESOURCE_PATH = path.resolve(__dirname, '..'); var runGrunt = require('./utils/run-grunt.js'); // build/node_modules/.bin/grunt "$@" From 94b4ec4ccb0c0aeabc262d6a1626d867cafa7c77 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 11:06:35 +0200 Subject: [PATCH 129/160] :green_heart: Add missing require statement --- script/grunt | 1 + 1 file changed, 1 insertion(+) diff --git a/script/grunt b/script/grunt index 50f5930fa..10f3beac5 100755 --- a/script/grunt +++ b/script/grunt @@ -1,4 +1,5 @@ #!/usr/bin/env node +var path = require('path'); process.env.ATOM_RESOURCE_PATH = path.resolve(__dirname, '..'); var runGrunt = require('./utils/run-grunt.js'); From 9bdc88ad32accf086bf66327844db48fbf0d33ec Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 11:51:57 +0200 Subject: [PATCH 130/160] Export ATOM_RESOURCE_PATH in Gruntfile.coffee if unset --- build/Gruntfile.coffee | 2 ++ script/grunt | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 653e1e268..1f3d889bd 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -14,6 +14,8 @@ _ = require 'underscore-plus' packageJson = require '../package.json' module.exports = (grunt) -> + process.env.ATOM_RESOURCE_PATH ?= path.resolve(__dirname, '..'); + require('time-grunt')(grunt) grunt.loadNpmTasks('grunt-babel') diff --git a/script/grunt b/script/grunt index 10f3beac5..99f6860d2 100755 --- a/script/grunt +++ b/script/grunt @@ -1,6 +1,4 @@ #!/usr/bin/env node -var path = require('path'); -process.env.ATOM_RESOURCE_PATH = path.resolve(__dirname, '..'); var runGrunt = require('./utils/run-grunt.js'); // build/node_modules/.bin/grunt "$@" From 921ff851670f4fe8e78753a254112a15a282537d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 11:59:48 +0200 Subject: [PATCH 131/160] Remove trailing semicolon --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 1f3d889bd..5cf88175e 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -14,7 +14,7 @@ _ = require 'underscore-plus' packageJson = require '../package.json' module.exports = (grunt) -> - process.env.ATOM_RESOURCE_PATH ?= path.resolve(__dirname, '..'); + process.env.ATOM_RESOURCE_PATH ?= path.resolve(__dirname, '..') require('time-grunt')(grunt) From e4946a1892ab49963fc32c47aeb22159e5f8cee9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 14:58:23 +0200 Subject: [PATCH 132/160] Make Atom executable as a standard Electron app --- package.json | 1 + ...r-start.coffee => crash-reporter-start.js} | 6 +- src/main-process/atom-portable.coffee | 35 --- src/main-process/atom-portable.js | 56 ++++ src/main-process/main.coffee | 198 ------------- src/main-process/main.js | 259 ++++++++++++++++++ 6 files changed, 319 insertions(+), 236 deletions(-) rename src/{crash-reporter-start.coffee => crash-reporter-start.js} (66%) delete mode 100644 src/main-process/atom-portable.coffee create mode 100644 src/main-process/atom-portable.js delete mode 100644 src/main-process/main.coffee create mode 100644 src/main-process/main.js diff --git a/package.json b/package.json index 717c0e00d..64529598f 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "clear-cut": "^2.0.1", "coffee-script": "1.8.0", "color": "^0.7.3", + "dedent": "0.6.0", "devtron": "1.1.0", "event-kit": "^1.5.0", "find-parent-dir": "^0.3.0", diff --git a/src/crash-reporter-start.coffee b/src/crash-reporter-start.js similarity index 66% rename from src/crash-reporter-start.coffee rename to src/crash-reporter-start.js index 47aae2469..98b210d06 100644 --- a/src/crash-reporter-start.coffee +++ b/src/crash-reporter-start.js @@ -1,6 +1,5 @@ -module.exports = (extra) -> - {crashReporter} = require 'electron' - +module.exports = function (extra) { + const {crashReporter} = require('electron') crashReporter.start({ productName: 'Atom', companyName: 'GitHub', @@ -8,3 +7,4 @@ module.exports = (extra) -> autoSubmit: false, extra: extra }) +} diff --git a/src/main-process/atom-portable.coffee b/src/main-process/atom-portable.coffee deleted file mode 100644 index ae4bb67ec..000000000 --- a/src/main-process/atom-portable.coffee +++ /dev/null @@ -1,35 +0,0 @@ -fs = require 'fs-plus' -path = require 'path' -{ipcMain} = require 'electron' - -module.exports = -class AtomPortable - @getPortableAtomHomePath: -> - execDirectoryPath = path.dirname(process.execPath) - path.join(execDirectoryPath, '..', '.atom') - - @setPortable: (existingAtomHome) -> - fs.copySync(existingAtomHome, @getPortableAtomHomePath()) - - @isPortableInstall: (platform, environmentAtomHome, defaultHome) -> - return false unless platform in ['linux', 'win32'] - return false if environmentAtomHome - return false if not fs.existsSync(@getPortableAtomHomePath()) - # currently checking only that the directory exists and is writable, - # probably want to do some integrity checks on contents in future - @isPortableAtomHomePathWritable(defaultHome) - - @isPortableAtomHomePathWritable: (defaultHome) -> - writable = false - message = "" - try - writePermissionTestFile = path.join(@getPortableAtomHomePath(), "write.test") - fs.writeFileSync(writePermissionTestFile, "test") if not fs.existsSync(writePermissionTestFile) - fs.removeSync(writePermissionTestFile) - writable = true - catch error - message = "Failed to use portable Atom home directory (#{@getPortableAtomHomePath()}). Using the default instead (#{defaultHome}). #{error.message}" - - ipcMain.on 'check-portable-home-writable', (event) -> - event.sender.send 'check-portable-home-writable-response', {writable, message} - writable diff --git a/src/main-process/atom-portable.js b/src/main-process/atom-portable.js new file mode 100644 index 000000000..339625ab3 --- /dev/null +++ b/src/main-process/atom-portable.js @@ -0,0 +1,56 @@ +const fs = require('fs-plus') +const path = require('path') +const {ipcMain} = require('electron') + +module.exports = class AtomPortable { + static getPortableAtomHomePath () { + var execDirectoryPath = path.dirname(process.execPath) + return path.join(execDirectoryPath, '..', '.atom') + } + + static setPortable (existingAtomHome) { + fs.copySync(existingAtomHome, this.getPortableAtomHomePath()) + } + + static isPortableInstall (platform, environmentAtomHome, defaultHome) { + if (!['linux', 'win32'].includes(platform)) { + return false + } + + if (environmentAtomHome) { + return false + } + + if (!fs.existsSync(this.getPortableAtomHomePath())) { + return false + } + + return this.isPortableAtomHomePathWritable(defaultHome) + } + + static isPortableAtomHomePathWritable (defaultHome) { + let writable = false + let message = '' + try { + const writePermissionTestFile = path.join(this.getPortableAtomHomePath(), 'write.test') + + if (!fs.existsSync(writePermissionTestFile)) { + fs.writeFileSync(writePermissionTestFile, 'test') + } + + fs.removeSync(writePermissionTestFile) + writable = true + } catch (error) { + message = `Failed to use portable Atom home directory (${this.getPortableAtomHomePath()}). Using the default instead (${defaultHome}). ${error.message}.` + } + + ipcMain.on('check-portable-home-writable', function (event) { + event.sender.send('check-portable-home-writable-response', { + writable: writable, + message: message + }) + }) + + return writable + } +} diff --git a/src/main-process/main.coffee b/src/main-process/main.coffee deleted file mode 100644 index 5368710aa..000000000 --- a/src/main-process/main.coffee +++ /dev/null @@ -1,198 +0,0 @@ -global.shellStartTime = Date.now() - -process.on 'uncaughtException', (error={}) -> - console.log(error.message) if error.message? - console.log(error.stack) if error.stack? - -{app} = require 'electron' -fs = require 'fs-plus' -path = require 'path' -temp = require 'temp' -yargs = require 'yargs' -previousConsoleLog = console.log -startCrashReporter = require('../crash-reporter-start') -console.log = require 'nslog' - -start = -> - args = parseCommandLine() - args.env = process.env - setupAtomHome(args) - setupCompileCache() - if handleStartupEventWithSquirrel() - return - else if args.test and args.mainProcess - console.log = previousConsoleLog - testRunner = require(path.join(args.resourcePath, 'spec/main-process/mocha-test-runner')) - app.on 'ready', -> testRunner(args.pathsToOpen) - return - - # NB: This prevents Win10 from showing dupe items in the taskbar - app.setAppUserModelId('com.squirrel.atom.atom') - - addPathToOpen = (event, pathToOpen) -> - event.preventDefault() - args.pathsToOpen.push(pathToOpen) - - addUrlToOpen = (event, urlToOpen) -> - event.preventDefault() - args.urlsToOpen.push(urlToOpen) - - app.on 'open-file', addPathToOpen - app.on 'open-url', addUrlToOpen - app.on 'will-finish-launching', startCrashReporter - - if args.userDataDir? - app.setPath('userData', args.userDataDir) - else if args.test - app.setPath('userData', temp.mkdirSync('atom-test-data')) - - app.on 'ready', -> - app.removeListener 'open-file', addPathToOpen - app.removeListener 'open-url', addUrlToOpen - - AtomApplication = require path.join(args.resourcePath, 'src', 'main-process', 'atom-application') - AtomApplication.open(args) - - console.log("App load time: #{Date.now() - global.shellStartTime}ms") unless args.test - -normalizeDriveLetterName = (filePath) -> - if process.platform is 'win32' - filePath.replace /^([a-z]):/, ([driveLetter]) -> driveLetter.toUpperCase() + ":" - else - filePath - -handleStartupEventWithSquirrel = -> - return false unless process.platform is 'win32' - SquirrelUpdate = require './squirrel-update' - squirrelCommand = process.argv[1] - SquirrelUpdate.handleStartupEvent(app, squirrelCommand) - -setupAtomHome = ({setPortable}) -> - return if process.env.ATOM_HOME - - atomHome = path.join(app.getPath('home'), '.atom') - AtomPortable = require './atom-portable' - - if setPortable and not AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome) - try - AtomPortable.setPortable(atomHome) - catch error - console.log("Failed copying portable directory '#{atomHome}' to '#{AtomPortable.getPortableAtomHomePath()}'") - console.log("#{error.message} #{error.stack}") - - if AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome) - atomHome = AtomPortable.getPortableAtomHomePath() - - try - atomHome = fs.realpathSync(atomHome) - - process.env.ATOM_HOME = atomHome - -setupCompileCache = -> - compileCache = require('../compile-cache') - compileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - -writeFullVersion = -> - process.stdout.write """ - Atom : #{app.getVersion()} - Electron: #{process.versions.electron} - Chrome : #{process.versions.chrome} - Node : #{process.versions.node} - - """ - -parseCommandLine = -> - version = app.getVersion() - options = yargs(process.argv[1..]).wrap(100) - options.usage """ - Atom Editor v#{version} - - Usage: atom [options] [path ...] - - One or more paths to files or folders may be specified. If there is an - existing Atom window that contains all of the given folders, the paths - will be opened in that window. Otherwise, they will be opened in a new - window. - - Environment Variables: - - ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode. - Defaults to `~/github/atom`. - - ATOM_HOME The root path for all configuration files and folders. - Defaults to `~/.atom`. - """ - # Deprecated 1.0 API preview flag - options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.') - options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.') - options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.') - options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the main process in the foreground.') - options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.') - options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.') - options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.') - options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.') - options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.') - options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.') - options.boolean('portable').describe('portable', 'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.') - options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.') - options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.') - options.string('timeout').describe('timeout', 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).') - options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.') - options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.') - options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.') - options.string('socket-path') - options.string('user-data-dir') - options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.') - - args = options.argv - - if args.help - process.stdout.write(options.help()) - process.exit(0) - - if args.version - writeFullVersion() - process.exit(0) - - addToLastWindow = args['add'] - executedFrom = args['executed-from']?.toString() ? process.cwd() - devMode = args['dev'] - safeMode = args['safe'] - pathsToOpen = args._ - test = args['test'] - mainProcess = args['main-process'] - timeout = args['timeout'] - newWindow = args['new-window'] - pidToKillWhenClosed = args['pid'] if args['wait'] - logFile = args['log-file'] - socketPath = args['socket-path'] - userDataDir = args['user-data-dir'] - profileStartup = args['profile-startup'] - clearWindowState = args['clear-window-state'] - urlsToOpen = [] - devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH ? path.join(app.getPath('home'), 'github', 'atom') - setPortable = args.portable - - if args['resource-path'] - devMode = true - resourcePath = args['resource-path'] - - devMode = true if test - resourcePath ?= devResourcePath if devMode - - unless fs.statSyncNoException(resourcePath) - resourcePath = path.dirname(path.dirname(__dirname)) - - # On Yosemite the $PATH is not inherited by the "open" command, so we have to - # explicitly pass it by command line, see http://git.io/YC8_Ew. - process.env.PATH = args['path-environment'] if args['path-environment'] - - resourcePath = normalizeDriveLetterName(resourcePath) - devResourcePath = normalizeDriveLetterName(devResourcePath) - - {resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test, - version, pidToKillWhenClosed, devMode, safeMode, newWindow, - logFile, socketPath, userDataDir, profileStartup, timeout, setPortable, - clearWindowState, addToLastWindow, mainProcess} - -start() diff --git a/src/main-process/main.js b/src/main-process/main.js new file mode 100644 index 000000000..9bbc32d09 --- /dev/null +++ b/src/main-process/main.js @@ -0,0 +1,259 @@ +global.shellStartTime = Date.now() + +process.on('uncaughtException', function (error = {}) { + if (error.message != null) { + console.log(error.message) + } + + if (error.stack != null) { + console.log(error.stack) + } +}) + +const {app} = require('electron') +const fs = require('fs-plus') +const path = require('path') +const temp = require('temp') +const yargs = require('yargs') +const dedent = require('dedent') +const previousConsoleLog = console.log +console.log = require('nslog') + +function start () { + const args = parseCommandLine() + args.env = process.env + setupAtomHome(args) + setupCompileCache() + + if (handleStartupEventWithSquirrel()) { + return + } else if (args.test && args.mainProcess) { + console.log = previousConsoleLog + app.on('ready', function () { + const testRunner = require(path.join(args.resourcePath, 'spec/main-process/mocha-test-runner')) + testRunner(args.pathsToOpen) + }) + return + } + + app.setAppUserModelId('com.squirrel.atom.atom') + + const startCrashReporter = require('../crash-reporter-start') + function addPathToOpen (event, pathToOpen) { + event.preventDefault() + args.pathsToOpen.push(pathToOpen) + } + + function addUrlToOpen (event, urlToOpen) { + event.preventDefault() + args.urlsToOpen.push(urlToOpen) + } + + app.on('open-file', addPathToOpen) + app.on('open-url', addUrlToOpen) + app.on('will-finish-launching', startCrashReporter) + + if (args.userDataDir != null) { + app.setPath('userData', args.userDataDir) + } else if (args.test) { + app.setPath('userData', temp.mkdirSync('atom-test-data')) + } + + app.on('ready', function () { + app.removeListener('open-file', addPathToOpen) + app.removeListener('open-url', addUrlToOpen) + const AtomApplication = require(path.join(args.resourcePath, 'src', 'main-process', 'atom-application')) + AtomApplication.open(args) + + if (!args.test) { + console.log(`App load time: ${Date.now() - global.shellStartTime}ms`) + } + }) +} + +function normalizeDriveLetterName (filePath) { + if (process.platform === 'win32') { + return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':') + } else { + return filePath + } +} + +function handleStartupEventWithSquirrel () { + if (process.platform !== 'win32') { + return false + } + + const SquirrelUpdate = require('./squirrel-update') + const squirrelCommand = process.argv[1] + return SquirrelUpdate.handleStartupEvent(app, squirrelCommand) +} + +function setupAtomHome ({setPortable}) { + if (process.env.ATOM_HOME) { + return + } + + let atomHome = path.join(app.getPath('home'), '.atom') + const AtomPortable = require('./atom-portable') + + if (setPortable && !AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)) { + try { + AtomPortable.setPortable(atomHome) + } catch (error) { + console.log(`Failed copying portable directory '${atomHome}' to '${AtomPortable.getPortableAtomHomePath()}'`) + console.log(`${error.message} ${error.stack}`) + } + } + + if (AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)) { + atomHome = AtomPortable.getPortableAtomHomePath() + } + + try { + atomHome = fs.realpathSync(atomHome) + } finally { + process.env.ATOM_HOME = atomHome + } +} + +function setupCompileCache () { + const CompileCache = require('../compile-cache') + CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) +} + +function writeFullVersion () { + process.stdout.write( + `Atom : ${app.getVersion()}\n` + + `Electron: ${process.versions.electron}\n` + + `Chrome : ${process.versions.chrome}\n` + + `Node : ${process.versions.node}\n` + ) +} + +function parseCommandLine () { + const options = yargs(process.argv.slice(1)).wrap(100) + const version = app.getVersion() + options.usage( + dedent`Atom Editor v${version} + + Usage: atom [options] [path ...] + + One or more paths to files or folders may be specified. If there is an + existing Atom window that contains all of the given folders, the paths + will be opened in that window. Otherwise, they will be opened in a new + window. + + Environment Variables: + + ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode. + Defaults to \`~/github/atom\`. + + ATOM_HOME The root path for all configuration files and folders. + Defaults to \`~/.atom\`.` + ) + options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.') + options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.') + options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.') + options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the main process in the foreground.') + options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.') + options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.') + options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.') + options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.') + options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.') + options.boolean('safe').describe( + 'safe', + 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.' + ) + options.boolean('portable').describe( + 'portable', + 'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.' + ) + options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.') + options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.') + options.string('timeout').describe( + 'timeout', + 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).' + ) + options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.') + options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.') + options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.') + options.string('socket-path') + options.string('user-data-dir') + options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.') + + const args = options.argv + + if (args.help) { + process.stdout.write(options.help()) + process.exit(0) + } + + if (args.version) { + writeFullVersion() + process.exit(0) + } + + const addToLastWindow = args['add'] + let devMode = args['dev'] + const safeMode = args['safe'] + const pathsToOpen = args._ + const test = args['test'] + const mainProcess = args['main-process'] + const timeout = args['timeout'] + const newWindow = args['new-window'] + let executedFrom = null + if (args['executed-from'] && args['executed-from'].toString()) { + executedFrom = args['executed-from'].toString() + } else { + executedFrom = process.cwd() + } + + let pidToKillWhenClosed = null + if (args['wait']) { + pidToKillWhenClosed = args['pid'] + } + + const logFile = args['log-file'] + const socketPath = args['socket-path'] + const userDataDir = args['user-data-dir'] + const profileStartup = args['profile-startup'] + const clearWindowState = args['clear-window-state'] + const urlsToOpen = [] + const setPortable = args.portable + let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom') + let resourcePath = null + + if (args['resource-path']) { + devMode = true + resourcePath = args['resource-path'] + } + + if (test) { + devMode = true + } + + if (devMode && !resourcePath) { + resourcePath = devResourcePath + } + + if (!fs.statSyncNoException(resourcePath)) { + resourcePath = path.dirname(path.dirname(__dirname)) + } + + if (args['path-environment']) { + process.env.PATH = args['path-environment'] + } + + resourcePath = normalizeDriveLetterName(resourcePath) + devResourcePath = normalizeDriveLetterName(devResourcePath) + + return { + resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test, + version, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, socketPath, + userDataDir, profileStartup, timeout, setPortable, clearWindowState, + addToLastWindow, mainProcess + } +} + +start() From 4fc049461ca0628b22ab65bb8600083d8f547c6e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 14:59:24 +0200 Subject: [PATCH 133/160] `var` -> `const` --- src/main-process/atom-portable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main-process/atom-portable.js b/src/main-process/atom-portable.js index 339625ab3..24d1b1429 100644 --- a/src/main-process/atom-portable.js +++ b/src/main-process/atom-portable.js @@ -4,7 +4,7 @@ const {ipcMain} = require('electron') module.exports = class AtomPortable { static getPortableAtomHomePath () { - var execDirectoryPath = path.dirname(process.execPath) + const execDirectoryPath = path.dirname(process.execPath) return path.join(execDirectoryPath, '..', '.atom') } From ccccafd4eaddfae53bc8fb560ed18efbf569165b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 15:00:24 +0200 Subject: [PATCH 134/160] :art: --- src/main-process/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main-process/main.js b/src/main-process/main.js index 9bbc32d09..8161da183 100644 --- a/src/main-process/main.js +++ b/src/main-process/main.js @@ -16,6 +16,7 @@ const path = require('path') const temp = require('temp') const yargs = require('yargs') const dedent = require('dedent') +const startCrashReporter = require('../crash-reporter-start') const previousConsoleLog = console.log console.log = require('nslog') @@ -38,7 +39,6 @@ function start () { app.setAppUserModelId('com.squirrel.atom.atom') - const startCrashReporter = require('../crash-reporter-start') function addPathToOpen (event, pathToOpen) { event.preventDefault() args.pathsToOpen.push(pathToOpen) @@ -195,7 +195,6 @@ function parseCommandLine () { } const addToLastWindow = args['add'] - let devMode = args['dev'] const safeMode = args['safe'] const pathsToOpen = args._ const test = args['test'] @@ -221,6 +220,7 @@ function parseCommandLine () { const clearWindowState = args['clear-window-state'] const urlsToOpen = [] const setPortable = args.portable + let devMode = args['dev'] let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom') let resourcePath = null From 9ad9a96b34f15ccac9a38163dca5431750a9f841 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 15:09:08 +0200 Subject: [PATCH 135/160] Copy comments --- src/main-process/atom-portable.js | 2 ++ src/main-process/main.js | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/main-process/atom-portable.js b/src/main-process/atom-portable.js index 24d1b1429..7d395c0e7 100644 --- a/src/main-process/atom-portable.js +++ b/src/main-process/atom-portable.js @@ -25,6 +25,8 @@ module.exports = class AtomPortable { return false } + // Currently checking only that the directory exists and is writable, + // probably want to do some integrity checks on contents in future. return this.isPortableAtomHomePathWritable(defaultHome) } diff --git a/src/main-process/main.js b/src/main-process/main.js index 8161da183..432f73832 100644 --- a/src/main-process/main.js +++ b/src/main-process/main.js @@ -37,6 +37,7 @@ function start () { return } + // NB: This prevents Win10 from showing dupe items in the taskbar app.setAppUserModelId('com.squirrel.atom.atom') function addPathToOpen (event, pathToOpen) { @@ -152,6 +153,7 @@ function parseCommandLine () { ATOM_HOME The root path for all configuration files and folders. Defaults to \`~/.atom\`.` ) + // Deprecated 1.0 API preview flag options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.') options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.') options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.') @@ -242,6 +244,8 @@ function parseCommandLine () { } if (args['path-environment']) { + // On Yosemite the $PATH is not inherited by the "open" command, so we have to + // explicitly pass it by command line, see http://git.io/YC8_Ew. process.env.PATH = args['path-environment'] } From e5da1011d4de9ff9251797f1f5a0093c5b57bd3d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 27 Jul 2016 20:01:52 +0200 Subject: [PATCH 136/160] :arrow_up: :green_heart: language-html Signed-off-by: Nathan Sobo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64529598f..29b64f38c 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "language-gfm": "0.88.0", "language-git": "0.15.0", "language-go": "0.42.1", - "language-html": "0.45.0", + "language-html": "0.45.1", "language-hyperlink": "0.16.0", "language-java": "0.23.0", "language-javascript": "0.119.0", From 67046ff2d972b44418b0fcd9d2edab94874d2395 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Jul 2016 14:46:41 -0600 Subject: [PATCH 137/160] :arrow_up: tree-view to address flaky specs (hopefully) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29b64f38c..488e26db3 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "symbols-view": "0.113.0", "tabs": "0.100.0", "timecop": "0.33.2", - "tree-view": "0.208.1", + "tree-view": "0.208.2", "update-package-dependencies": "0.10.0", "welcome": "0.34.0", "whitespace": "0.33.0", From 7c79a5b9739994027a8db5af61c84a8da838e29b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Jul 2016 12:16:54 -0600 Subject: [PATCH 138/160] Fix regression where spacebar scrolled elements containing editors /cc @hellendag --- src/text-editor-component.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index e6fc0dc15..3949f18e5 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -365,7 +365,12 @@ class TextEditorComponent onTextInput: (event) => event.stopPropagation() - event.preventDefault() + + # WARNING: If we call preventDefault on the input of a space character, + # then the browser interprets the spacebar keypress as a page-down command, + # causing spaces to scroll elements containing editors. This is impossible + # to test. + event.preventDefault() if event.data isnt ' ' return unless @isInputEnabled() From 0aa4256bcf40a1d4cbef7601bfb4e0c5c34cdb47 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Thu, 28 Jul 2016 10:16:37 -0700 Subject: [PATCH 139/160] :arrow_up: settings-view@0.241.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 488e26db3..58174153d 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "notifications": "0.65.0", "open-on-github": "1.2.0", "package-generator": "1.0.0", - "settings-view": "0.240.1", + "settings-view": "0.241.0", "snippets": "1.0.2", "spell-check": "0.67.1", "status-bar": "1.4.0", From e0cc48f17e2c4ccbdbb6b4e18eca7fba2de1b88b Mon Sep 17 00:00:00 2001 From: Hubot Date: Thu, 28 Jul 2016 13:29:20 -0500 Subject: [PATCH 140/160] 1.11.0-dev --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58174153d..f3b6c86f9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.10.0-dev", + "version": "1.11.0-dev", "description": "A hackable text editor for the 21st Century.", "main": "./src/main-process/main.js", "repository": { From ebd68515d2e036d3fd935b7a83284620c151cd25 Mon Sep 17 00:00:00 2001 From: Hubot Date: Thu, 28 Jul 2016 13:29:20 -0500 Subject: [PATCH 141/160] 1.10.0-beta0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58174153d..c78267a40 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.10.0-dev", + "version": "1.10.0-beta0", "description": "A hackable text editor for the 21st Century.", "main": "./src/main-process/main.js", "repository": { From e249b26a3876a6efb12a6cf85d14c14cca20dacc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Jul 2016 15:34:38 -0600 Subject: [PATCH 142/160] Fix regex to allow multi-digit minor versions in build script Signed-off-by: Antonio Scandurra --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 5cf88175e..451752829 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -320,7 +320,7 @@ getDefaultChannelAndReleaseBranch = (version) -> else channel = 'stable' - minorVersion = version.match(/^\d\.\d/)[0] + minorVersion = version.match(/^\d+\.\d+/)[0] releaseBranch = "#{minorVersion}-releases" [channel, releaseBranch] From 002c776f1088e61ed17f943e326c4d978b7cf844 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Jul 2016 15:34:38 -0600 Subject: [PATCH 143/160] Fix regex to allow multi-digit minor versions in build script Signed-off-by: Antonio Scandurra --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 5cf88175e..451752829 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -320,7 +320,7 @@ getDefaultChannelAndReleaseBranch = (version) -> else channel = 'stable' - minorVersion = version.match(/^\d\.\d/)[0] + minorVersion = version.match(/^\d+\.\d+/)[0] releaseBranch = "#{minorVersion}-releases" [channel, releaseBranch] From 45b93e6df839db0abb91eb505bb3659fae19e6fa Mon Sep 17 00:00:00 2001 From: Machiste Quintana Date: Thu, 28 Jul 2016 19:53:36 -0700 Subject: [PATCH 144/160] :memo: Add JS style guide to the Contributing guide --- CONTRIBUTING.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f7d539ca..837961e6a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,6 +20,7 @@ These are just guidelines, not rules, use your best judgment and feel free to pr [Styleguides](#styleguides) * [Git Commit Messages](#git-commit-messages) + * [JavaScript Styleguide](#javascript-styleguide) * [CoffeeScript Styleguide](#coffeescript-styleguide) * [Specs Styleguide](#specs-styleguide) * [Documentation Styleguide](#documentation-styleguide) @@ -280,6 +281,25 @@ If you want to read about using Atom or developing packages in Atom, the [Atom F * :arrow_down: `:arrow_down:` when downgrading dependencies * :shirt: `:shirt:` when removing linter warnings +### JavaScript Styleguide + +All JavaScript must adhere to [JavaScript Standard Style](http://standardjs.com/). + +* Prefer `Object.assign()` to the object spread operator (`{...anotherObj}`) +* Inline `export`s with expressions + ```js + // Use this: + export default class ClassName { + + } + + // Instead of: + class ClassName { + + } + export default ClassName + ``` + ### CoffeeScript Styleguide * Set parameter defaults without spaces around the equal sign From fd94acc2e832c7d01fe6c9ab9b5441cbd77f0af3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 29 Jul 2016 17:12:44 +0200 Subject: [PATCH 145/160] Delete RowMap and its specs After transitioning to `DisplayLayer` we don't need this object anymore. --- spec/row-map-spec.coffee | 104 --------------------------------- src/row-map.coffee | 120 --------------------------------------- 2 files changed, 224 deletions(-) delete mode 100644 spec/row-map-spec.coffee delete mode 100644 src/row-map.coffee diff --git a/spec/row-map-spec.coffee b/spec/row-map-spec.coffee deleted file mode 100644 index e89ac1259..000000000 --- a/spec/row-map-spec.coffee +++ /dev/null @@ -1,104 +0,0 @@ -RowMap = require '../src/row-map' - -describe "RowMap", -> - map = null - - beforeEach -> - map = new RowMap - - describe "::screenRowRangeForBufferRow(bufferRow)", -> - it "returns the range of screen rows corresponding to the given buffer row", -> - map.spliceRegions(0, 0, [ - {bufferRows: 5, screenRows: 5} - {bufferRows: 1, screenRows: 5} - {bufferRows: 5, screenRows: 5} - {bufferRows: 5, screenRows: 1} - ]) - - expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 1] - expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 10] - expect(map.screenRowRangeForBufferRow(6)).toEqual [10, 11] - expect(map.screenRowRangeForBufferRow(11)).toEqual [15, 16] - expect(map.screenRowRangeForBufferRow(12)).toEqual [15, 16] - expect(map.screenRowRangeForBufferRow(16)).toEqual [16, 17] - - describe "::bufferRowRangeForScreenRow(screenRow)", -> - it "returns the range of buffer rows corresponding to the given screen row", -> - map.spliceRegions(0, 0, [ - {bufferRows: 5, screenRows: 5} - {bufferRows: 1, screenRows: 5} - {bufferRows: 5, screenRows: 5} - {bufferRows: 5, screenRows: 1} - ]) - - expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1] - expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 6] - expect(map.bufferRowRangeForScreenRow(6)).toEqual [5, 6] - expect(map.bufferRowRangeForScreenRow(10)).toEqual [6, 7] - expect(map.bufferRowRangeForScreenRow(14)).toEqual [10, 11] - expect(map.bufferRowRangeForScreenRow(15)).toEqual [11, 16] - expect(map.bufferRowRangeForScreenRow(16)).toEqual [16, 17] - - describe "::spliceRegions(startBufferRow, bufferRowCount, regions)", -> - it "can insert regions when empty", -> - regions = [ - {bufferRows: 5, screenRows: 5} - {bufferRows: 1, screenRows: 5} - {bufferRows: 5, screenRows: 5} - {bufferRows: 5, screenRows: 1} - ] - map.spliceRegions(0, 0, regions) - expect(map.getRegions()).toEqual regions - - it "can insert wrapped lines into rectangular regions", -> - map.spliceRegions(0, 0, [{bufferRows: 10, screenRows: 10}]) - map.spliceRegions(5, 0, [{bufferRows: 1, screenRows: 3}]) - expect(map.getRegions()).toEqual [ - {bufferRows: 5, screenRows: 5} - {bufferRows: 1, screenRows: 3} - {bufferRows: 5, screenRows: 5} - ] - - it "can splice wrapped lines into rectangular regions", -> - map.spliceRegions(0, 0, [{bufferRows: 10, screenRows: 10}]) - map.spliceRegions(5, 1, [{bufferRows: 1, screenRows: 3}]) - expect(map.getRegions()).toEqual [ - {bufferRows: 5, screenRows: 5} - {bufferRows: 1, screenRows: 3} - {bufferRows: 4, screenRows: 4} - ] - - it "can splice folded lines into rectangular regions", -> - map.spliceRegions(0, 0, [{bufferRows: 10, screenRows: 10}]) - map.spliceRegions(5, 3, [{bufferRows: 3, screenRows: 1}]) - expect(map.getRegions()).toEqual [ - {bufferRows: 5, screenRows: 5} - {bufferRows: 3, screenRows: 1} - {bufferRows: 2, screenRows: 2} - ] - - it "can replace folded regions with a folded region that surrounds them", -> - map.spliceRegions(0, 0, [ - {bufferRows: 3, screenRows: 3} - {bufferRows: 3, screenRows: 1} - {bufferRows: 1, screenRows: 1} - {bufferRows: 3, screenRows: 1} - {bufferRows: 3, screenRows: 3} - ]) - map.spliceRegions(2, 8, [{bufferRows: 8, screenRows: 1}]) - expect(map.getRegions()).toEqual [ - {bufferRows: 2, screenRows: 2} - {bufferRows: 8, screenRows: 1} - {bufferRows: 3, screenRows: 3} - ] - - it "merges adjacent rectangular regions", -> - map.spliceRegions(0, 0, [ - {bufferRows: 3, screenRows: 3} - {bufferRows: 3, screenRows: 1} - {bufferRows: 1, screenRows: 1} - {bufferRows: 3, screenRows: 1} - {bufferRows: 3, screenRows: 3} - ]) - - map.spliceRegions(3, 7, [{bufferRows: 5, screenRows: 5}]) diff --git a/src/row-map.coffee b/src/row-map.coffee deleted file mode 100644 index 5510c1421..000000000 --- a/src/row-map.coffee +++ /dev/null @@ -1,120 +0,0 @@ -{spliceWithArray} = require 'underscore-plus' - -# Used by the display buffer to map screen rows to buffer rows and vice-versa. -# This mapping may not be 1:1 due to folds and soft-wraps. This object maintains -# an array of regions, which contain `bufferRows` and `screenRows` fields. -# -# Rectangular Regions: -# If a region has the same number of buffer rows and screen rows, it is referred -# to as "rectangular", and represents one or more non-soft-wrapped, non-folded -# lines. -# -# Trapezoidal Regions: -# If a region has one buffer row and more than one screen row, it represents a -# soft-wrapped line. If a region has one screen row and more than one buffer -# row, it represents folded lines -module.exports = -class RowMap - constructor: -> - @regions = [] - - # Public: Returns a copy of all the regions in the map - getRegions: -> - @regions.slice() - - # Public: Returns an end-row-exclusive range of screen rows corresponding to - # the given buffer row. If the buffer row is soft-wrapped, the range may span - # multiple screen rows. Otherwise it will span a single screen row. - screenRowRangeForBufferRow: (targetBufferRow) -> - {region, bufferRows, screenRows} = @traverseToBufferRow(targetBufferRow) - - if region? and region.bufferRows isnt region.screenRows - [screenRows, screenRows + region.screenRows] - else - screenRows += targetBufferRow - bufferRows - [screenRows, screenRows + 1] - - # Public: Returns an end-row-exclusive range of buffer rows corresponding to - # the given screen row. If the screen row is the first line of a folded range - # of buffer rows, the range may span multiple buffer rows. Otherwise it will - # span a single buffer row. - bufferRowRangeForScreenRow: (targetScreenRow) -> - {region, screenRows, bufferRows} = @traverseToScreenRow(targetScreenRow) - if region? and region.bufferRows isnt region.screenRows - [bufferRows, bufferRows + region.bufferRows] - else - bufferRows += targetScreenRow - screenRows - [bufferRows, bufferRows + 1] - - # Public: If the given buffer row is part of a folded row range, returns that - # row range. Otherwise returns a range spanning only the given buffer row. - bufferRowRangeForBufferRow: (targetBufferRow) -> - {region, bufferRows} = @traverseToBufferRow(targetBufferRow) - if region? and region.bufferRows isnt region.screenRows - [bufferRows, bufferRows + region.bufferRows] - else - [targetBufferRow, targetBufferRow + 1] - - # Public: Given a starting buffer row, the number of buffer rows to replace, - # and an array of regions of shape {bufferRows: n, screenRows: m}, splices - # the regions at the appropriate location in the map. This method is used by - # display buffer to keep the map updated when the underlying buffer changes. - spliceRegions: (startBufferRow, bufferRowCount, regions) -> - endBufferRow = startBufferRow + bufferRowCount - {index, bufferRows} = @traverseToBufferRow(startBufferRow) - precedingRows = startBufferRow - bufferRows - - count = 0 - while region = @regions[index + count] - count++ - bufferRows += region.bufferRows - if bufferRows >= endBufferRow - followingRows = bufferRows - endBufferRow - break - - if precedingRows > 0 - regions.unshift({bufferRows: precedingRows, screenRows: precedingRows}) - - if followingRows > 0 - regions.push({bufferRows: followingRows, screenRows: followingRows}) - - spliceWithArray(@regions, index, count, regions) - @mergeAdjacentRectangularRegions(index - 1, index + regions.length) - - traverseToBufferRow: (targetBufferRow) -> - bufferRows = 0 - screenRows = 0 - for region, index in @regions - if (bufferRows + region.bufferRows) > targetBufferRow - return {region, index, screenRows, bufferRows} - bufferRows += region.bufferRows - screenRows += region.screenRows - {index, screenRows, bufferRows} - - traverseToScreenRow: (targetScreenRow) -> - bufferRows = 0 - screenRows = 0 - for region, index in @regions - if (screenRows + region.screenRows) > targetScreenRow - return {region, index, screenRows, bufferRows} - bufferRows += region.bufferRows - screenRows += region.screenRows - {index, screenRows, bufferRows} - - mergeAdjacentRectangularRegions: (startIndex, endIndex) -> - for index in [endIndex..startIndex] - if 0 < index < @regions.length - leftRegion = @regions[index - 1] - rightRegion = @regions[index] - leftIsRectangular = leftRegion.bufferRows is leftRegion.screenRows - rightIsRectangular = rightRegion.bufferRows is rightRegion.screenRows - if leftIsRectangular and rightIsRectangular - @regions.splice index - 1, 2, - bufferRows: leftRegion.bufferRows + rightRegion.bufferRows - screenRows: leftRegion.screenRows + rightRegion.screenRows - return - - # Public: Returns an array of strings describing the map's regions. - inspect: -> - for {bufferRows, screenRows} in @regions - "#{bufferRows}:#{screenRows}" From 6d4102a09883cbfaedc0e6a9441eafd591d55526 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 29 Jul 2016 17:15:06 +0200 Subject: [PATCH 146/160] Delete random-editor-spec.coffee We are already extensively testing the same specs on text-buffer. --- spec/random-editor-spec.coffee | 91 ---------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 spec/random-editor-spec.coffee diff --git a/spec/random-editor-spec.coffee b/spec/random-editor-spec.coffee deleted file mode 100644 index 699e60b21..000000000 --- a/spec/random-editor-spec.coffee +++ /dev/null @@ -1,91 +0,0 @@ -{times, random} = require 'underscore-plus' -randomWords = require 'random-words' -TextBuffer = require 'text-buffer' -TextEditor = require '../src/text-editor' - -describe "TextEditor", -> - [editor, tokenizedBuffer, buffer, steps] = [] - - softWrapColumn = 80 - - beforeEach -> - atom.config.set('editor.softWrapAtPreferredLineLength', true) - atom.config.set('editor.preferredLineLength', softWrapColumn) - - it "properly renders soft-wrapped lines when randomly mutated", -> - times 10, (i) -> - buffer = new TextBuffer - editor = atom.workspace.buildTextEditor({buffer}) - editor.setEditorWidthInChars(80) - tokenizedBuffer = editor.tokenizedBuffer - steps = [] - - times 30, -> - randomlyMutateEditor() - verifyLines() - - verifyLines = -> - {bufferRows, screenLines} = getReferenceScreenLines() - for referenceBufferRow, screenRow in bufferRows - referenceScreenLine = screenLines[screenRow] - actualBufferRow = editor.bufferRowForScreenRow(screenRow) - unless actualBufferRow is referenceBufferRow - logLines() - throw new Error("Invalid buffer row #{actualBufferRow} for screen row #{screenRow}", ) - - actualScreenLine = editor.lineTextForScreenRow(screenRow) - unless actualScreenLine is referenceScreenLine - logLines() - throw new Error("Invalid line text at screen row #{screenRow}") - - logLines = -> - console.log "==== screen lines ====" - editor.logScreenLines() - console.log "==== reference lines ====" - {bufferRows, screenLines} = getReferenceScreenLines() - for bufferRow, screenRow in bufferRows - console.log screenRow, bufferRow, screenLines[screenRow].text - console.log "==== steps to reproduce this failure: ===" - for step in steps - console.log 'editor.' + step[0] + '('+ step[1..].map((a) -> JSON.stringify(a)).join(', ') + ')' - - randomlyMutateEditor = -> - if Math.random() < .2 - softWrapped = not editor.isSoftWrapped() - steps.push(['setSoftWrapped', softWrapped]) - editor.setSoftWrapped(softWrapped) - else - range = getRandomRange() - text = getRandomText() - steps.push(['setTextInBufferRange', range, text]) - editor.setTextInBufferRange(range, text) - - getRandomRange = -> - startRow = random(0, buffer.getLastRow()) - startColumn = random(0, buffer.lineForRow(startRow).length) - endRow = random(startRow, buffer.getLastRow()) - endColumn = random(0, buffer.lineForRow(endRow).length) - [[startRow, startColumn], [endRow, endColumn]] - - getRandomText = -> - text = [] - max = buffer.getText().split(/\s/).length * 0.75 - - times random(5, max), -> - if Math.random() < .1 - text += '\n' - else - text += " " if /\w$/.test(text) - text += randomWords(exactly: 1) - text - - getReferenceScreenLines = -> - referenceEditor = atom.workspace.buildTextEditor() - referenceEditor.setEditorWidthInChars(80) - referenceEditor.setText(editor.getText()) - referenceEditor.setSoftWrapped(editor.isSoftWrapped()) - - screenLines = [0..referenceEditor.getLastScreenRow()].map (row) -> referenceEditor.lineTextForScreenRow(row) - bufferRows = referenceEditor.bufferRowsForScreenRows(0, referenceEditor.getLastScreenRow()) - - {screenLines, bufferRows} From 1fd51ee2710f59b26c50929d16c3f74cf3c9e9c3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 29 Jul 2016 15:11:37 -0600 Subject: [PATCH 147/160] :arrow_up: text-buffer --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3b6c86f9..211ab39be 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "sinon": "1.17.4", "source-map-support": "^0.3.2", "temp": "0.8.1", - "text-buffer": "9.2.2", + "text-buffer": "9.2.3", "typescript-simple": "1.0.0", "underscore-plus": "^1.6.6", "winreg": "^1.2.1", From acc5052978c82701be0a5d6c180e61ceb1c8b0d3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 29 Jul 2016 15:11:37 -0600 Subject: [PATCH 148/160] :arrow_up: text-buffer --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c78267a40..fe0649740 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "sinon": "1.17.4", "source-map-support": "^0.3.2", "temp": "0.8.1", - "text-buffer": "9.2.2", + "text-buffer": "9.2.3", "typescript-simple": "1.0.0", "underscore-plus": "^1.6.6", "winreg": "^1.2.1", From 82efce08ed9f329c2dfe380f896171a6d51310af Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Fri, 29 Jul 2016 14:48:33 -0700 Subject: [PATCH 149/160] Fix WinShell closure/for issue, improve error handling --- src/main-process/win-shell.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee index 39e9f4ed0..973859597 100644 --- a/src/main-process/win-shell.coffee +++ b/src/main-process/win-shell.coffee @@ -13,11 +13,11 @@ class ShellOption isRegistered: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) .get @parts[0].name, (err, val) => - callback(not err? and val.value is @parts[0].value) + callback(not err? and val? and val.value is @parts[0].value) register: (callback) => doneCount = @parts.length - for part in @parts + @parts.forEach (part) => reg = new Registry({hive: 'HKCU', key: if part.key? then "#{@key}\\#{part.key}" else @key}) reg.create( -> reg.set part.name, Registry.REG_SZ, part.value, -> callback() if --doneCount is 0) @@ -31,7 +31,7 @@ class ShellOption update: (callback) => new Registry({hive: 'HKCU', key: "#{@key}\\#{@parts[0].key}"}) .get @parts[0].name, (err, val) => - if err? or not val.value.includes '\\' + exeName + if err? or not val? or val.value.includes '\\' + exeName callback(err) else @register callback From f3caa671092f2460eea7bc5a148628ce343dbe80 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Fri, 29 Jul 2016 15:51:45 -0700 Subject: [PATCH 150/160] Ensure beta is detected from path --- src/main-process/win-shell.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main-process/win-shell.coffee b/src/main-process/win-shell.coffee index 973859597..2bb993e9c 100644 --- a/src/main-process/win-shell.coffee +++ b/src/main-process/win-shell.coffee @@ -3,7 +3,8 @@ Path = require 'path' exeName = Path.basename(process.execPath) appPath = "\"#{process.execPath}\"" -appName = exeName.replace('atom', 'Atom').replace('beta', 'Beta').replace('.exe', '') +isBeta = appPath.includes(' Beta') +appName = exeName.replace('atom', (if isBeta then 'Atom Beta' else 'Atom' )).replace('.exe', '') class ShellOption constructor: (key, parts) -> From ec3207e6c0c069815465d1b3f567f8dde0939d62 Mon Sep 17 00:00:00 2001 From: simurai Date: Sun, 31 Jul 2016 14:26:13 +0200 Subject: [PATCH 151/160] :arrow_up: settings-view@v0.241.1 https://github.com/atom/settings-view/pull/822 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 211ab39be..50a266d56 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "notifications": "0.65.0", "open-on-github": "1.2.0", "package-generator": "1.0.0", - "settings-view": "0.241.0", + "settings-view": "0.241.1", "snippets": "1.0.2", "spell-check": "0.67.1", "status-bar": "1.4.0", From 475ad6b4e6dfa2cd42425386d8e63a5d9526419b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 1 Aug 2016 16:14:20 -0600 Subject: [PATCH 152/160] :arrow_up: about --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50a266d56..1704f02f4 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "one-light-syntax": "1.3.0", "solarized-dark-syntax": "1.0.2", "solarized-light-syntax": "1.0.2", - "about": "1.5.3", + "about": "1.6.0", "archive-view": "0.61.1", "autocomplete-atom-api": "0.10.0", "autocomplete-css": "0.11.2", From 3fd275a7f65781cc6eb55b0f3f2c48656aad80ed Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 1 Aug 2016 15:52:59 -0700 Subject: [PATCH 153/160] Convert Color to JS --- src/color.coffee | 89 ------------------------------- src/color.js | 134 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 89 deletions(-) delete mode 100644 src/color.coffee create mode 100644 src/color.js diff --git a/src/color.coffee b/src/color.coffee deleted file mode 100644 index b413b9e2c..000000000 --- a/src/color.coffee +++ /dev/null @@ -1,89 +0,0 @@ -_ = require 'underscore-plus' -ParsedColor = null - -# Essential: A simple color class returned from {Config::get} when the value -# at the key path is of type 'color'. -module.exports = -class Color - # Essential: Parse a {String} or {Object} into a {Color}. - # - # * `value` A {String} such as `'white'`, `#ff00ff`, or - # `'rgba(255, 15, 60, .75)'` or an {Object} with `red`, `green`, `blue`, - # and `alpha` properties. - # - # Returns a {Color} or `null` if it cannot be parsed. - @parse: (value) -> - return null if _.isArray(value) or _.isFunction(value) - return null unless _.isObject(value) or _.isString(value) - - ParsedColor ?= require 'color' - - try - parsedColor = new ParsedColor(value) - catch error - return null - - new Color(parsedColor.red(), parsedColor.green(), parsedColor.blue(), parsedColor.alpha()) - - constructor: (red, green, blue, alpha) -> - Object.defineProperties this, - red: - set: (newRed) -> red = parseColor(newRed) - get: -> red - enumerable: true - configurable: false - green: - set: (newGreen) -> green = parseColor(newGreen) - get: -> green - enumerable: true - configurable: false - blue: - set: (newBlue) -> blue = parseColor(newBlue) - get: -> blue - enumerable: true - configurable: false - alpha: - set: (newAlpha) -> alpha = parseAlpha(newAlpha) - get: -> alpha - enumerable: true - configurable: false - - @red = red - @green = green - @blue = blue - @alpha = alpha - - # Essential: Returns a {String} in the form `'#abcdef'`. - toHexString: -> - "##{numberToHexString(@red)}#{numberToHexString(@green)}#{numberToHexString(@blue)}" - - # Essential: Returns a {String} in the form `'rgba(25, 50, 75, .9)'`. - toRGBAString: -> - "rgba(#{@red}, #{@green}, #{@blue}, #{@alpha})" - - isEqual: (color) -> - return true if this is color - color = Color.parse(color) unless color instanceof Color - return false unless color? - color.red is @red and color.blue is @blue and color.green is @green and color.alpha is @alpha - - clone: -> new Color(@red, @green, @blue, @alpha) - -parseColor = (color) -> - color = parseInt(color) - color = 0 if isNaN(color) - color = Math.max(color, 0) - color = Math.min(color, 255) - color - -parseAlpha = (alpha) -> - alpha = parseFloat(alpha) - alpha = 1 if isNaN(alpha) - alpha = Math.max(alpha, 0) - alpha = Math.min(alpha, 1) - alpha - -numberToHexString = (number) -> - hex = number.toString(16) - hex = "0#{hex}" if number < 16 - hex diff --git a/src/color.js b/src/color.js new file mode 100644 index 000000000..9db9e9b16 --- /dev/null +++ b/src/color.js @@ -0,0 +1,134 @@ +/** @babel */ + +let ParsedColor = null + +// Essential: A simple color class returned from {Config::get} when the value +// at the key path is of type 'color'. +export default class Color { + // Essential: Parse a {String} or {Object} into a {Color}. + // + // * `value` A {String} such as `'white'`, `#ff00ff`, or + // `'rgba(255, 15, 60, .75)'` or an {Object} with `red`, `green`, `blue`, + // and `alpha` properties. + // + // Returns a {Color} or `null` if it cannot be parsed. + static parse (value) { + switch (typeof value) { + case 'string': + break + case 'object': + if (Array.isArray(value)) { return null } + break + default: + return null + } + + if (!ParsedColor) { + ParsedColor = require('color') + } + + try { + var parsedColor = new ParsedColor(value) + } catch (error) { + return null + } + + return new Color(parsedColor.red(), parsedColor.green(), parsedColor.blue(), parsedColor.alpha()) + } + + constructor (red, green, blue, alpha) { + this.red = red + this.green = green + this.blue = blue + this.alpha = alpha + } + + set red (red) { + this._red = parseColor(red) + } + + set green (green) { + this._green = parseColor(green) + } + + set blue (blue) { + this._blue = parseColor(blue) + } + + set alpha (alpha) { + this._alpha = parseAlpha(alpha) + } + + get red () { + return this._red + } + + get green () { + return this._green + } + + get blue () { + return this._blue + } + + get alpha () { + return this._alpha + } + + // Essential: Returns a {String} in the form `'#abcdef'`. + toHexString () { + return `#${numberToHexString(this.red)}${numberToHexString(this.green)}${numberToHexString(this.blue)}` + } + + // Essential: Returns a {String} in the form `'rgba(25, 50, 75, .9)'`. + toRGBAString () { + return `rgba(${this.red}, ${this.green}, ${this.blue}, ${this.alpha})` + } + + isEqual (color) { + if (this === color) { + return true + } + + if (!(color instanceof Color)) { + color = Color.parse(color) + } + + if (color == null) { + return false + } + + return color.red === this.red && color.blue === this.blue && color.green === this.green && color.alpha === this.alpha + } + + clone () { + return new Color(this.red, this.green, this.blue, this.alpha) + } +} + +function parseColor (colorString) { + const color = parseInt(colorString, 10) + if (isNaN(color)) { + return 0 + } else { + return Math.min(Math.max(color, 0), 255) + } +} + +function parseAlpha (alphaString) { + const alpha = parseFloat(alphaString) + if (isNaN(alpha)) { + return 1 + } else { + return Math.min(Math.max(alpha, 0), 1) + } +} + +function numberToHexString (number) { + const hex = number.toString(16) + if (number < 16) { + return `0${hex}` + } else { + return hex + } +} From 2500d59bcef79eed44c179ce37c5c4a7e61d39d8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 1 Aug 2016 15:57:18 -0700 Subject: [PATCH 154/160] Generate API docs from js sources --- build/package.json | 1 + build/tasks/docs-task.coffee | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/build/package.json b/build/package.json index 533f49417..97f93e7ab 100644 --- a/build/package.json +++ b/build/package.json @@ -30,6 +30,7 @@ "grunt-peg": "~1.1.0", "grunt-shell": "~0.3.1", "grunt-standard": "^2.0.0", + "joanna": "0.0.3", "legal-eagle": "~0.13.0", "minidump": "~0.9", "npm": "3.10.5", diff --git a/build/tasks/docs-task.coffee b/build/tasks/docs-task.coffee index 75e21de8a..5b05688a0 100644 --- a/build/tasks/docs-task.coffee +++ b/build/tasks/docs-task.coffee @@ -4,6 +4,7 @@ fs = require 'fs-plus' _ = require 'underscore-plus' donna = require 'donna' +joanna = require 'joanna' tello = require 'tello' module.exports = (grunt) -> @@ -30,8 +31,16 @@ module.exports = (grunt) -> grunt.registerTask 'build-docs', 'Builds the API docs in src', -> docsOutputDir = grunt.config.get('docsOutputDir') - metadata = donna.generateMetadata(['.']) - api = tello.digest(metadata) + [coffeeMetadata] = donna.generateMetadata(['.']) + jsMetadata = joanna('.') + + metadata = { + repository: coffeeMetadata.repository, + version: coffeeMetadata.version, + files: Object.assign(coffeeMetadata.files, jsMetadata.files) + } + + api = tello.digest([metadata]) _.extend(api.classes, getClassesToInclude()) api.classes = sortClasses(api.classes) From 61bbfae420431b9124f5982e9e33dcc640503aa5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 1 Aug 2016 16:20:26 -0700 Subject: [PATCH 155/160] :arrow_up: joanna --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index 97f93e7ab..8a41ac980 100644 --- a/build/package.json +++ b/build/package.json @@ -30,7 +30,7 @@ "grunt-peg": "~1.1.0", "grunt-shell": "~0.3.1", "grunt-standard": "^2.0.0", - "joanna": "0.0.3", + "joanna": "0.0.5", "legal-eagle": "~0.13.0", "minidump": "~0.9", "npm": "3.10.5", From 2e04bd6ea9dbc0513f4f65be4f8894e97609dcf9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 1 Aug 2016 16:21:11 -0700 Subject: [PATCH 156/160] Convert window.coffee and clipboard.coffee to javascript --- src/clipboard.coffee | 61 -------------------------------------- src/clipboard.js | 70 ++++++++++++++++++++++++++++++++++++++++++++ src/window.coffee | 27 ----------------- src/window.js | 30 +++++++++++++++++++ 4 files changed, 100 insertions(+), 88 deletions(-) delete mode 100644 src/clipboard.coffee create mode 100644 src/clipboard.js delete mode 100644 src/window.coffee create mode 100644 src/window.js diff --git a/src/clipboard.coffee b/src/clipboard.coffee deleted file mode 100644 index 9511bdda9..000000000 --- a/src/clipboard.coffee +++ /dev/null @@ -1,61 +0,0 @@ -crypto = require 'crypto' -clipboard = require './safe-clipboard' - -# Extended: Represents the clipboard used for copying and pasting in Atom. -# -# An instance of this class is always available as the `atom.clipboard` global. -# -# ## Examples -# -# ```coffee -# atom.clipboard.write('hello') -# -# console.log(atom.clipboard.read()) # 'hello' -# ``` -module.exports = -class Clipboard - constructor: -> - @reset() - - reset: -> - @metadata = null - @signatureForMetadata = null - - # Creates an `md5` hash of some text. - # - # * `text` A {String} to hash. - # - # Returns a hashed {String}. - md5: (text) -> - crypto.createHash('md5').update(text, 'utf8').digest('hex') - - # Public: Write the given text to the clipboard. - # - # The metadata associated with the text is available by calling - # {::readWithMetadata}. - # - # * `text` The {String} to store. - # * `metadata` (optional) The additional info to associate with the text. - write: (text, metadata) -> - @signatureForMetadata = @md5(text) - @metadata = metadata - clipboard.writeText(text) - - # Public: Read the text from the clipboard. - # - # Returns a {String}. - read: -> - clipboard.readText() - - # Public: Read the text from the clipboard and return both the text and the - # associated metadata. - # - # Returns an {Object} with the following keys: - # * `text` The {String} clipboard text. - # * `metadata` The metadata stored by an earlier call to {::write}. - readWithMetadata: -> - text = @read() - if @signatureForMetadata is @md5(text) - {text, @metadata} - else - {text} diff --git a/src/clipboard.js b/src/clipboard.js new file mode 100644 index 000000000..34f6b1f83 --- /dev/null +++ b/src/clipboard.js @@ -0,0 +1,70 @@ +/** @babel */ + +import crypto from 'crypto' +import clipboard from './safe-clipboard' + +// Extended: Represents the clipboard used for copying and pasting in Atom. +// +// An instance of this class is always available as the `atom.clipboard` global. +// +// ## Examples +// +// ```coffee +// atom.clipboard.write('hello') +// +// console.log(atom.clipboard.read()) # 'hello' +// ``` +export default class Clipboard { + constructor () { + this.reset() + } + + reset () { + this.metadata = null + this.signatureForMetadata = null + } + + // Creates an `md5` hash of some text. + // + // * `text` A {String} to hash. + // + // Returns a hashed {String}. + md5 (text) { + return crypto.createHash('md5').update(text, 'utf8').digest('hex') + } + + // Public: Write the given text to the clipboard. + // + // The metadata associated with the text is available by calling + // {::readWithMetadata}. + // + // * `text` The {String} to store. + // * `metadata` (optional) The additional info to associate with the text. + write (text, metadata) { + this.signatureForMetadata = this.md5(text) + this.metadata = metadata + clipboard.writeText(text) + } + + // Public: Read the text from the clipboard. + // + // Returns a {String}. + read () { + return clipboard.readText() + } + + // Public: Read the text from the clipboard and return both the text and the + // associated metadata. + // + // Returns an {Object} with the following keys: + // * `text` The {String} clipboard text. + // * `metadata` The metadata stored by an earlier call to {::write}. + readWithMetadata () { + let text = this.read() + if (this.signatureForMetadata === this.md5(text)) { + return {text, metadata: this.metadata} + } else { + return {text} + } + } +} diff --git a/src/window.coffee b/src/window.coffee deleted file mode 100644 index 9554218ca..000000000 --- a/src/window.coffee +++ /dev/null @@ -1,27 +0,0 @@ -# Public: Measure how long a function takes to run. -# -# description - A {String} description that will be logged to the console when -# the function completes. -# fn - A {Function} to measure the duration of. -# -# Returns the value returned by the given function. -window.measure = (description, fn) -> - start = Date.now() - value = fn() - result = Date.now() - start - console.log description, result - value - -# Public: Create a dev tools profile for a function. -# -# description - A {String} description that will be available in the Profiles -# tab of the dev tools. -# fn - A {Function} to profile. -# -# Returns the value returned by the given function. -window.profile = (description, fn) -> - measure description, -> - console.profile(description) - value = fn() - console.profileEnd(description) - value diff --git a/src/window.js b/src/window.js new file mode 100644 index 000000000..c4f28ba96 --- /dev/null +++ b/src/window.js @@ -0,0 +1,30 @@ +// Public: Measure how long a function takes to run. +// +// description - A {String} description that will be logged to the console when +// the function completes. +// fn - A {Function} to measure the duration of. +// +// Returns the value returned by the given function. +window.measure = function (description, fn) { + let start = Date.now() + let value = fn() + let result = Date.now() - start + console.log(description, result) + return value +} + +// Public: Create a dev tools profile for a function. +// +// description - A {String} description that will be available in the Profiles +// tab of the dev tools. +// fn - A {Function} to profile. +// +// Returns the value returned by the given function. +window.profile = function (description, fn) { + window.measure(description, function () { + console.profile(description) + let value = fn() + console.profileEnd(description) + return value + }) +} From b358047b96ba6733c8139399008c51dc75e5e25a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 1 Aug 2016 16:33:42 -0700 Subject: [PATCH 157/160] Convert DeserializerManager to JS --- src/deserializer-manager.coffee | 68 ---------------------- src/deserializer-manager.js | 100 ++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 68 deletions(-) delete mode 100644 src/deserializer-manager.coffee create mode 100644 src/deserializer-manager.js diff --git a/src/deserializer-manager.coffee b/src/deserializer-manager.coffee deleted file mode 100644 index 3c73a0b02..000000000 --- a/src/deserializer-manager.coffee +++ /dev/null @@ -1,68 +0,0 @@ -{Disposable} = require 'event-kit' - -# Extended: Manages the deserializers used for serialized state -# -# An instance of this class is always available as the `atom.deserializers` -# global. -# -# ## Examples -# -# ```coffee -# class MyPackageView extends View -# atom.deserializers.add(this) -# -# @deserialize: (state) -> -# new MyPackageView(state) -# -# constructor: (@state) -> -# -# serialize: -> -# @state -# ``` -module.exports = -class DeserializerManager - constructor: (@atomEnvironment) -> - @deserializers = {} - - # Public: Register the given class(es) as deserializers. - # - # * `deserializers` One or more deserializers to register. A deserializer can - # be any object with a `.name` property and a `.deserialize()` method. A - # common approach is to register a *constructor* as the deserializer for its - # instances by adding a `.deserialize()` class method. When your method is - # called, it will be passed serialized state as the first argument and the - # {Atom} environment object as the second argument, which is useful if you - # wish to avoid referencing the `atom` global. - add: (deserializers...) -> - @deserializers[deserializer.name] = deserializer for deserializer in deserializers - new Disposable => - delete @deserializers[deserializer.name] for deserializer in deserializers - return - - getDeserializerCount: -> - Object.keys(@deserializers).length - - # Public: Deserialize the state and params. - # - # * `state` The state {Object} to deserialize. - deserialize: (state) -> - return unless state? - - if deserializer = @get(state) - stateVersion = state.get?('version') ? state.version - return if deserializer.version? and deserializer.version isnt stateVersion - deserializer.deserialize(state, @atomEnvironment) - else - console.warn "No deserializer found for", state - - # Get the deserializer for the state. - # - # * `state` The state {Object} being deserialized. - get: (state) -> - return unless state? - - name = state.get?('deserializer') ? state.deserializer - @deserializers[name] - - clear: -> - @deserializers = {} diff --git a/src/deserializer-manager.js b/src/deserializer-manager.js new file mode 100644 index 000000000..f5f2e6429 --- /dev/null +++ b/src/deserializer-manager.js @@ -0,0 +1,100 @@ +/** @babel */ + +import {Disposable} from 'event-kit' + +// Extended: Manages the deserializers used for serialized state +// +// An instance of this class is always available as the `atom.deserializers` +// global. +// +// ## Examples +// +// ```coffee +// class MyPackageView extends View +// atom.deserializers.add(this) +// +// @deserialize: (state) -> +// new MyPackageView(state) +// +// constructor: (@state) -> +// +// serialize: -> +// @state +// ``` +export default class DeserializerManager { + constructor (atomEnvironment) { + this.atomEnvironment = atomEnvironment + this.deserializers = {} + } + + // Public: Register the given class(es) as deserializers. + // + // * `deserializers` One or more deserializers to register. A deserializer can + // be any object with a `.name` property and a `.deserialize()` method. A + // common approach is to register a *constructor* as the deserializer for its + // instances by adding a `.deserialize()` class method. When your method is + // called, it will be passed serialized state as the first argument and the + // {Atom} environment object as the second argument, which is useful if you + // wish to avoid referencing the `atom` global. + add (...deserializers) { + for (let i = 0; i < deserializers.length; i++) { + let deserializer = deserializers[i] + this.deserializers[deserializer.name] = deserializer + } + + return new Disposable(() => { + for (let j = 0; j < deserializers.length; j++) { + let deserializer = deserializers[j] + delete this.deserializers[deserializer.name] + } + }) + } + + getDeserializerCount () { + return Object.keys(this.deserializers).length + } + + // Public: Deserialize the state and params. + // + // * `state` The state {Object} to deserialize. + deserialize (state) { + if (state == null) { + return + } + + const deserializer = this.get(state) + if (deserializer) { + let stateVersion = ( + (typeof state.get === 'function') && state.get('version') || + state.version + ) + + if ((deserializer.version != null) && deserializer.version !== stateVersion) { + return + } + return deserializer.deserialize(state, this.atomEnvironment) + } else { + return console.warn('No deserializer found for', state) + } + } + + // Get the deserializer for the state. + // + // * `state` The state {Object} being deserialized. + get (state) { + if (state == null) { + return + } + + let stateDeserializer = ( + (typeof state.get === 'function') && state.get('deserializer') || + state.deserializer + ) + + return this.deserializers[stateDeserializer] + } + + clear () { + this.deserializers = {} + } +} From ebcffb1c8b95e0384a650e5fb2c859e3e07aadd7 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 2 Aug 2016 11:18:11 -0700 Subject: [PATCH 158/160] Run joanna with an explicit list of paths --- build/package.json | 2 +- build/tasks/docs-task.coffee | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/package.json b/build/package.json index 8a41ac980..98a806134 100644 --- a/build/package.json +++ b/build/package.json @@ -30,7 +30,7 @@ "grunt-peg": "~1.1.0", "grunt-shell": "~0.3.1", "grunt-standard": "^2.0.0", - "joanna": "0.0.5", + "joanna": "0.0.6", "legal-eagle": "~0.13.0", "minidump": "~0.9", "npm": "3.10.5", diff --git a/build/tasks/docs-task.coffee b/build/tasks/docs-task.coffee index 5b05688a0..1e80eb2ce 100644 --- a/build/tasks/docs-task.coffee +++ b/build/tasks/docs-task.coffee @@ -6,6 +6,7 @@ _ = require 'underscore-plus' donna = require 'donna' joanna = require 'joanna' tello = require 'tello' +glob = require 'glob' module.exports = (grunt) -> getClassesToInclude = -> @@ -32,7 +33,7 @@ module.exports = (grunt) -> docsOutputDir = grunt.config.get('docsOutputDir') [coffeeMetadata] = donna.generateMetadata(['.']) - jsMetadata = joanna('.') + jsMetadata = joanna(glob.sync('src/*.js')) metadata = { repository: coffeeMetadata.repository, From 2b5f1bda469527ffe89ca80e7d7181146dc26dbf Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 2 Aug 2016 12:19:45 -0600 Subject: [PATCH 159/160] Always seek to specified position in TokenizedBufferIterator Fixes #10350 Signed-off-by: Antonio Scandurra --- spec/tokenized-buffer-iterator-spec.js | 204 ++++++++++++++++--------- spec/tokenized-buffer-spec.coffee | 2 +- src/tokenized-buffer-iterator.coffee | 25 +-- 3 files changed, 145 insertions(+), 86 deletions(-) diff --git a/spec/tokenized-buffer-iterator-spec.js b/spec/tokenized-buffer-iterator-spec.js index 8d0e458f4..93aaf21e0 100644 --- a/spec/tokenized-buffer-iterator-spec.js +++ b/spec/tokenized-buffer-iterator-spec.js @@ -4,100 +4,152 @@ import TokenizedBufferIterator from '../src/tokenized-buffer-iterator' import {Point} from 'text-buffer' describe('TokenizedBufferIterator', () => { - it('reports two boundaries at the same position when tags close, open, then close again without a non-negative integer separating them (regression)', () => { - const tokenizedBuffer = { - tokenizedLineForRow () { - return { - tags: [-1, -2, -1, -2], - text: '', - openScopes: [] - } - } - } - - const grammarRegistry = { - scopeForId () { - return 'foo' - } - } - - const iterator = new TokenizedBufferIterator(tokenizedBuffer, grammarRegistry) - - iterator.seek(Point(0, 0)) - expect(iterator.getPosition()).toEqual(Point(0, 0)) - expect(iterator.getCloseTags()).toEqual([]) - expect(iterator.getOpenTags()).toEqual(['foo']) - - iterator.moveToSuccessor() - expect(iterator.getPosition()).toEqual(Point(0, 0)) - expect(iterator.getCloseTags()).toEqual(['foo']) - expect(iterator.getOpenTags()).toEqual(['foo']) - - iterator.moveToSuccessor() - expect(iterator.getCloseTags()).toEqual(['foo']) - expect(iterator.getOpenTags()).toEqual([]) - }) - - it("reports a boundary at line end if the next line's open scopes don't match the containing tags for the current line", () => { - const tokenizedBuffer = { - tokenizedLineForRow (row) { - if (row === 0) { + describe('seek(position)', function () { + it('seeks to the leftmost tag boundary at the given position, returning the containing tags', function () { + const tokenizedBuffer = { + tokenizedLineForRow (row) { return { - tags: [-1, 3, -2, -3], - text: 'bar', + tags: [-1, -2, -3, -4, -5, 3, -3, -4, -6], + text: 'foo', openScopes: [] } - } else if (row === 1) { + } + } + + const grammarRegistry = { + scopeForId (id) { return { - tags: [3], - text: 'baz', - openScopes: [-1] - } - } else if (row === 2) { + '-1': 'foo', '-2': 'foo', + '-3': 'bar', '-4': 'bar', + '-5': 'baz', '-6': 'baz' + }[id] + } + } + + const iterator = new TokenizedBufferIterator(tokenizedBuffer, grammarRegistry) + + expect(iterator.seek(Point(0, 0))).toEqual([]) + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual(['foo']) + + iterator.moveToSuccessor() + expect(iterator.getCloseTags()).toEqual(['foo']) + expect(iterator.getOpenTags()).toEqual(['bar']) + + expect(iterator.seek(Point(0, 1))).toEqual(['baz']) + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual([]) + + iterator.moveToSuccessor() + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual(['bar']) + + expect(iterator.seek(Point(0, 3))).toEqual(['baz']) + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual(['bar']) + + iterator.moveToSuccessor() + expect(iterator.getCloseTags()).toEqual(['bar', 'baz']) + expect(iterator.getOpenTags()).toEqual([]) + }) + }) + + describe('moveToSuccessor()', function () { + it('reports two boundaries at the same position when tags close, open, then close again without a non-negative integer separating them (regression)', () => { + const tokenizedBuffer = { + tokenizedLineForRow () { return { - tags: [-2], + tags: [-1, -2, -1, -2], text: '', - openScopes: [-1] + openScopes: [] } } } - } - const grammarRegistry = { - scopeForId (id) { - if (id === -2 || id === -1) { + const grammarRegistry = { + scopeForId () { return 'foo' - } else if (id === -3) { - return 'qux' } } - } - const iterator = new TokenizedBufferIterator(tokenizedBuffer, grammarRegistry) + const iterator = new TokenizedBufferIterator(tokenizedBuffer, grammarRegistry) - iterator.seek(Point(0, 0)) - expect(iterator.getPosition()).toEqual(Point(0, 0)) - expect(iterator.getCloseTags()).toEqual([]) - expect(iterator.getOpenTags()).toEqual(['foo']) + iterator.seek(Point(0, 0)) + expect(iterator.getPosition()).toEqual(Point(0, 0)) + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual(['foo']) - iterator.moveToSuccessor() - expect(iterator.getPosition()).toEqual(Point(0, 3)) - expect(iterator.getCloseTags()).toEqual(['foo']) - expect(iterator.getOpenTags()).toEqual(['qux']) + iterator.moveToSuccessor() + expect(iterator.getPosition()).toEqual(Point(0, 0)) + expect(iterator.getCloseTags()).toEqual(['foo']) + expect(iterator.getOpenTags()).toEqual(['foo']) - iterator.moveToSuccessor() - expect(iterator.getPosition()).toEqual(Point(0, 3)) - expect(iterator.getCloseTags()).toEqual(['qux']) - expect(iterator.getOpenTags()).toEqual([]) + iterator.moveToSuccessor() + expect(iterator.getCloseTags()).toEqual(['foo']) + expect(iterator.getOpenTags()).toEqual([]) + }) - iterator.moveToSuccessor() - expect(iterator.getPosition()).toEqual(Point(1, 0)) - expect(iterator.getCloseTags()).toEqual([]) - expect(iterator.getOpenTags()).toEqual(['foo']) + it("reports a boundary at line end if the next line's open scopes don't match the containing tags for the current line", () => { + const tokenizedBuffer = { + tokenizedLineForRow (row) { + if (row === 0) { + return { + tags: [-1, 3, -2, -3], + text: 'bar', + openScopes: [] + } + } else if (row === 1) { + return { + tags: [3], + text: 'baz', + openScopes: [-1] + } + } else if (row === 2) { + return { + tags: [-2], + text: '', + openScopes: [-1] + } + } + } + } - iterator.moveToSuccessor() - expect(iterator.getPosition()).toEqual(Point(2, 0)) - expect(iterator.getCloseTags()).toEqual(['foo']) - expect(iterator.getOpenTags()).toEqual([]) + const grammarRegistry = { + scopeForId (id) { + if (id === -2 || id === -1) { + return 'foo' + } else if (id === -3) { + return 'qux' + } + } + } + + const iterator = new TokenizedBufferIterator(tokenizedBuffer, grammarRegistry) + + iterator.seek(Point(0, 0)) + expect(iterator.getPosition()).toEqual(Point(0, 0)) + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual(['foo']) + + iterator.moveToSuccessor() + expect(iterator.getPosition()).toEqual(Point(0, 3)) + expect(iterator.getCloseTags()).toEqual(['foo']) + expect(iterator.getOpenTags()).toEqual(['qux']) + + iterator.moveToSuccessor() + expect(iterator.getPosition()).toEqual(Point(0, 3)) + expect(iterator.getCloseTags()).toEqual(['qux']) + expect(iterator.getOpenTags()).toEqual([]) + + iterator.moveToSuccessor() + expect(iterator.getPosition()).toEqual(Point(1, 0)) + expect(iterator.getCloseTags()).toEqual([]) + expect(iterator.getOpenTags()).toEqual(['foo']) + + iterator.moveToSuccessor() + expect(iterator.getPosition()).toEqual(Point(2, 0)) + expect(iterator.getCloseTags()).toEqual(['foo']) + expect(iterator.getOpenTags()).toEqual([]) + }) }) }) diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index d11c93213..6c437d953 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -816,7 +816,7 @@ describe "TokenizedBuffer", -> expect(iterator.seek(Point(0, 8))).toEqual(["source.js"]) expect(iterator.getPosition()).toEqual(Point(0, 8)) expect(iterator.seek(Point(1, 0))).toEqual(["source.js", "comment.block.js"]) - expect(iterator.getPosition()).toEqual(Point(1, 5)) + expect(iterator.getPosition()).toEqual(Point(1, 0)) expect(iterator.seek(Point(1, 18))).toEqual(["source.js", "constant.numeric.decimal.js"]) expect(iterator.getPosition()).toEqual(Point(1, 18)) diff --git a/src/tokenized-buffer-iterator.coffee b/src/tokenized-buffer-iterator.coffee index 780156e42..591943a48 100644 --- a/src/tokenized-buffer-iterator.coffee +++ b/src/tokenized-buffer-iterator.coffee @@ -18,24 +18,31 @@ class TokenizedBufferIterator @currentLineLength = currentLine.text.length @containingTags = @currentLineOpenTags.map (id) => @grammarRegistry.scopeForId(id) currentColumn = 0 + for tag, index in @currentTags if tag >= 0 - if currentColumn >= position.column and @isAtTagBoundary() + if currentColumn is position.column @tagIndex = index break else currentColumn += tag @containingTags.pop() while @closeTags.shift() - @containingTags.push(tag) while tag = @openTags.shift() - else - scopeName = @grammarRegistry.scopeForId(tag) - if tag % 2 is 0 - if @openTags.length > 0 + @containingTags.push(openTag) while openTag = @openTags.shift() + if currentColumn > position.column @tagIndex = index break - else - @closeTags.push(scopeName) - else + else + scopeName = @grammarRegistry.scopeForId(tag) + if tag % 2 is 0 # close tag + if @openTags.length > 0 + if currentColumn is position.column + @tagIndex = index + break + else + @containingTags.pop() while @closeTags.shift() + @containingTags.push(openTag) while openTag = @openTags.shift() + @closeTags.push(scopeName) + else # open tag @openTags.push(scopeName) @tagIndex ?= @currentTags.length From 9a72c7e65e543d7125300b294358af2f80616509 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 2 Aug 2016 12:14:00 -0700 Subject: [PATCH 160/160] Fix exception when package requires an incompatible native module --- spec/package-spec.coffee | 19 +++++++++++++++---- src/package.coffee | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index 92218e749..57d7a661f 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -24,14 +24,14 @@ describe "Package", -> mockLocalStorage() it "does not activate it", -> - packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') + packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-incompatible-native-module') pack = buildPackage(packagePath) expect(pack.isCompatible()).toBe false expect(pack.incompatibleModules[0].name).toBe 'native-module' expect(pack.incompatibleModules[0].path).toBe path.join(packagePath, 'node_modules', 'native-module') it "utilizes _atomModuleCache if present to determine the package's native dependencies", -> - packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-ignored-incompatible-native-module') + packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-ignored-incompatible-native-module') pack = buildPackage(packagePath) expect(pack.getNativeModuleDependencyPaths().length).toBe(1) # doesn't see the incompatible module expect(pack.isCompatible()).toBe true @@ -41,8 +41,7 @@ describe "Package", -> expect(pack.isCompatible()).toBe false it "caches the incompatible native modules in local storage", -> - packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - + packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-incompatible-native-module') expect(buildPackage(packagePath).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 1 expect(global.localStorage.setItem.callCount).toBe 1 @@ -51,6 +50,18 @@ describe "Package", -> expect(global.localStorage.getItem.callCount).toBe 2 expect(global.localStorage.setItem.callCount).toBe 1 + it "logs an error to the console describing the problem", -> + packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-incompatible-native-module') + + spyOn(console, 'warn') + spyOn(atom.notifications, 'addFatalError') + + buildPackage(packagePath).activateNow() + + expect(atom.notifications.addFatalError).not.toHaveBeenCalled() + expect(console.warn.callCount).toBe(1) + expect(console.warn.mostRecentCall.args[0]).toContain('it requires one or more incompatible native modules (native-module)') + describe "::rebuild()", -> beforeEach -> mockLocalStorage() diff --git a/src/package.coffee b/src/package.coffee index 1bb8a939c..94763f961 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -427,7 +427,7 @@ class Package return @mainModule if @mainModuleRequired unless @isCompatible() console.warn """ - Failed to require the main module of '#{@name}' because it requires one or more incompatible native modules (#{_.map(@incompatibleModules, 'name').join(', ')}). + Failed to require the main module of '#{@name}' because it requires one or more incompatible native modules (#{_.pluck(@incompatibleModules, 'name').join(', ')}). Run `apm rebuild` in the package directory and restart Atom to resolve. """ return