mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
Merge branch 'master' into ns-mb-detangle-editor
This commit is contained in:
14
.travis.yml
14
.travis.yml
@@ -13,14 +13,8 @@ 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
|
||||
- os: osx
|
||||
env: ATOM_SPECS_TASK=packages NODE_VERSION=0.12
|
||||
|
||||
sudo: false
|
||||
|
||||
@@ -28,16 +22,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 +39,11 @@ notifications:
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- build-essential
|
||||
- git
|
||||
- libgnome-keyring-dev
|
||||
- fakeroot
|
||||
- gcc-multilib
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)?
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||

|
||||
|
||||
[](https://travis-ci.org/atom/atom) [](https://ci.appveyor.com/project/Atom/atom)
|
||||
[](https://circleci.com/gh/atom/atom) [](https://travis-ci.org/atom/atom) [](https://ci.appveyor.com/project/Atom/atom)
|
||||
[](https://david-dm.org/atom/atom)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "1.10.0"
|
||||
"atom-package-manager": "1.12.5"
|
||||
}
|
||||
}
|
||||
|
||||
10
appveyor.yml
10
appveyor.yml
@@ -1,9 +1,5 @@
|
||||
version: "{build}"
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
skip_tags: true
|
||||
clone_folder: c:\projects\atom
|
||||
clone_depth: 10
|
||||
@@ -16,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%
|
||||
@@ -37,6 +34,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'
|
||||
|
||||
@@ -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')
|
||||
@@ -296,7 +298,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)
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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?
|
||||
|
||||
|
||||
@@ -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'
|
||||
@@ -34,7 +34,12 @@ module.exports = (gruntObject) ->
|
||||
grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', ->
|
||||
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()
|
||||
@@ -119,6 +124,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 +142,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 +161,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 +194,7 @@ createAtomDraftRelease = (isPrerelease, branchName, callback) ->
|
||||
callback(null, body)
|
||||
|
||||
deleteRelease = (release) ->
|
||||
grunt.log.ok("Deleting GitHub release #{release.tag_name}")
|
||||
options =
|
||||
uri: release.url
|
||||
method: 'DELETE'
|
||||
@@ -195,6 +205,7 @@ deleteRelease = (release) ->
|
||||
logError('Deleting release failed', error, body)
|
||||
|
||||
deleteExistingAssets = (release, assetNames, callback) ->
|
||||
grunt.log.ok("Deleting #{assetNames.join(',')} from GitHub release #{release.tag_name}")
|
||||
[callback, assetNames] = [assetNames, callback] if not callback?
|
||||
|
||||
deleteAsset = (url, callback) ->
|
||||
@@ -216,6 +227,7 @@ deleteExistingAssets = (release, assetNames, callback) ->
|
||||
|
||||
uploadAssets = (release, buildDir, assets, callback) ->
|
||||
uploadToReleases = (release, assetName, assetPath, callback) ->
|
||||
grunt.log.ok("Uploading #{assetName} to GitHub release #{release.tag_name}")
|
||||
options =
|
||||
uri: release.upload_url.replace(/\{.*$/, "?name=#{assetName}")
|
||||
method: 'POST'
|
||||
@@ -248,6 +260,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'
|
||||
|
||||
40
circle.yml
40
circle.yml
@@ -1,4 +1,38 @@
|
||||
machine:
|
||||
environment:
|
||||
XCODE_SCHEME: test
|
||||
XCODE_WORKSPACE: test
|
||||
XCODE_PROJECT: test
|
||||
|
||||
xcode:
|
||||
version: 7.3
|
||||
|
||||
general:
|
||||
branches:
|
||||
only:
|
||||
- io-circle-ci
|
||||
artifacts:
|
||||
- out/Atom.zip
|
||||
|
||||
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
|
||||
- npm install -g npm
|
||||
- script/fingerprint-clean
|
||||
|
||||
override:
|
||||
- script/bootstrap
|
||||
|
||||
post:
|
||||
- script/fingerprint-write
|
||||
|
||||
cache_directories:
|
||||
- apm/node_modules
|
||||
- build/node_modules
|
||||
- node_modules
|
||||
|
||||
test:
|
||||
override:
|
||||
- script/grunt ci
|
||||
|
||||
post:
|
||||
- zip -r out/Atom.zip out/Atom.app
|
||||
|
||||
@@ -18,6 +18,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
|
||||
|
||||
39
package.json
39
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": {
|
||||
@@ -70,8 +71,8 @@
|
||||
"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-light-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",
|
||||
"solarized-dark-syntax": "1.0.2",
|
||||
@@ -108,50 +109,50 @@
|
||||
"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",
|
||||
"styleguide": "0.47.0",
|
||||
"symbols-view": "0.113.0",
|
||||
"tabs": "0.99.0",
|
||||
"timecop": "0.33.1",
|
||||
"tree-view": "0.208.1",
|
||||
"tabs": "0.100.0",
|
||||
"timecop": "0.33.2",
|
||||
"tree-view": "0.208.2",
|
||||
"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",
|
||||
"language-coffee-script": "0.47.1",
|
||||
"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.14.0",
|
||||
"language-go": "0.42.0",
|
||||
"language-html": "0.44.1",
|
||||
"language-git": "0.15.0",
|
||||
"language-go": "0.42.1",
|
||||
"language-html": "0.45.1",
|
||||
"language-hyperlink": "0.16.0",
|
||||
"language-java": "0.23.0",
|
||||
"language-javascript": "0.119.0",
|
||||
"language-json": "0.18.1",
|
||||
"language-less": "0.29.4",
|
||||
"language-json": "0.18.2",
|
||||
"language-less": "0.29.5",
|
||||
"language-make": "0.22.2",
|
||||
"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.68.6",
|
||||
"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.22.0",
|
||||
"language-sql": "0.23.0",
|
||||
"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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
29
script/fingerprint-clean
Executable file
29
script/fingerprint-clean
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/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')
|
||||
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)
|
||||
}
|
||||
2
script/fingerprint-write
Executable file
2
script/fingerprint-write
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
require('./utils/fingerprint').writeFingerprint()
|
||||
@@ -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')
|
||||
},
|
||||
|
||||
|
||||
@@ -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,16 @@ 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
|
||||
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')
|
||||
|
||||
@@ -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()
|
||||
@@ -958,9 +959,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)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
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'
|
||||
extra: extra
|
||||
})
|
||||
10
src/crash-reporter-start.js
Normal file
10
src/crash-reporter-start.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = function (extra) {
|
||||
const {crashReporter} = require('electron')
|
||||
crashReporter.start({
|
||||
productName: 'Atom',
|
||||
companyName: 'GitHub',
|
||||
submitURL: 'https://crashreporter.atom.io',
|
||||
autoSubmit: false,
|
||||
extra: extra
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
58
src/main-process/atom-portable.js
Normal file
58
src/main-process/atom-portable.js
Normal file
@@ -0,0 +1,58 @@
|
||||
const fs = require('fs-plus')
|
||||
const path = require('path')
|
||||
const {ipcMain} = require('electron')
|
||||
|
||||
module.exports = class AtomPortable {
|
||||
static getPortableAtomHomePath () {
|
||||
const 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
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
263
src/main-process/main.js
Normal file
263
src/main-process/main.js
Normal file
@@ -0,0 +1,263 @@
|
||||
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 startCrashReporter = require('../crash-reporter-start')
|
||||
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
|
||||
}
|
||||
|
||||
// NB: This prevents Win10 from showing dupe items in the taskbar
|
||||
app.setAppUserModelId('com.squirrel.atom.atom')
|
||||
|
||||
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\`.`
|
||||
)
|
||||
// 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.')
|
||||
|
||||
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']
|
||||
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 devMode = args['dev']
|
||||
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']) {
|
||||
// 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']
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -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, '..')
|
||||
@@ -125,26 +125,36 @@ 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 ->
|
||||
WinRegistry.installContextMenu ->
|
||||
addCommandsToPath ->
|
||||
app.quit()
|
||||
addCommandsToPath ->
|
||||
WinShell.fileHandler.register ->
|
||||
updateContextMenus ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-updated'
|
||||
updateShortcuts ->
|
||||
WinRegistry.installContextMenu ->
|
||||
addCommandsToPath ->
|
||||
addCommandsToPath ->
|
||||
updateContextMenus ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-uninstall'
|
||||
removeShortcuts ->
|
||||
WinRegistry.uninstallContextMenu ->
|
||||
removeCommandsFromPath ->
|
||||
app.quit()
|
||||
removeCommandsFromPath ->
|
||||
WinShell.fileHandler.deregister ->
|
||||
WinShell.fileContextMenu.deregister ->
|
||||
WinShell.folderContextMenu.deregister ->
|
||||
WinShell.folderBackgroundContextMenu.deregister ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-obsolete'
|
||||
app.quit()
|
||||
|
||||
@@ -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)
|
||||
57
src/main-process/win-shell.coffee
Normal file
57
src/main-process/win-shell.coffee
Normal file
@@ -0,0 +1,57 @@
|
||||
Registry = require 'winreg'
|
||||
Path = require 'path'
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
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.includes '\\' + exeName
|
||||
callback(err)
|
||||
else
|
||||
@register callback
|
||||
|
||||
exports.appName = appName
|
||||
|
||||
exports.fileHandler = new ShellOption("\\Software\\Classes\\Applications\\#{exeName}",
|
||||
[{key: 'shell\\open\\command', name: '', value: "#{appPath} \"%1\""}]
|
||||
)
|
||||
|
||||
contextParts = [
|
||||
{key: 'command', name: '', value: "#{appPath} \"%1\""},
|
||||
{name: '', value: "Open with #{appName}"},
|
||||
{name: 'Icon', value: "#{appPath}"}
|
||||
]
|
||||
|
||||
exports.fileContextMenu = new ShellOption("\\Software\\Classes\\*\\shell\\#{appName}", contextParts)
|
||||
|
||||
exports.folderContextMenu = new ShellOption("\\Software\\Classes\\Directory\\shell\\#{appName}", contextParts)
|
||||
|
||||
exports.folderBackgroundContextMenu = new ShellOption("\\Software\\Classes\\Directory\\background\\shell\\#{appName}",
|
||||
JSON.parse(JSON.stringify(contextParts).replace('%1', '%V'))
|
||||
)
|
||||
@@ -159,6 +159,7 @@ class Package
|
||||
|
||||
# TODO: Remove. Settings view calls this method currently.
|
||||
activateConfig: ->
|
||||
return if @configSchemaRegisteredOnLoad
|
||||
@requireMainModule()
|
||||
@registerConfigSchemaFromMainModule()
|
||||
|
||||
|
||||
@@ -344,7 +344,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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user