Merge branch 'master' into tree-sitter-injections
@@ -15,7 +15,7 @@ matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
env: NODE_VERSION=6.9.4 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1
|
||||
env: NODE_VERSION=8.9.3 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1
|
||||
|
||||
sudo: required
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ environment:
|
||||
global:
|
||||
ATOM_DEV_RESOURCE_PATH: c:\projects\atom
|
||||
TEST_JUNIT_XML_ROOT: c:\projects\junit-test-results
|
||||
NODE_VERSION: 6.9.4
|
||||
NODE_VERSION: 8.9.3
|
||||
|
||||
matrix:
|
||||
- TASK: test
|
||||
@@ -36,7 +36,6 @@ install:
|
||||
- IF NOT EXIST %TEST_JUNIT_XML_ROOT% MKDIR %TEST_JUNIT_XML_ROOT%
|
||||
- SET PATH=C:\Program Files\Atom\resources\cli;%PATH%
|
||||
- ps: Install-Product node $env:NODE_VERSION $env:PLATFORM
|
||||
- npm install -g npm@5.3.0
|
||||
|
||||
build_script:
|
||||
- CD %APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
10
atom.sh
@@ -13,6 +13,9 @@ case $(basename $0) in
|
||||
atom-beta)
|
||||
CHANNEL=beta
|
||||
;;
|
||||
atom-nightly)
|
||||
CHANNEL=nightly
|
||||
;;
|
||||
atom-dev)
|
||||
CHANNEL=dev
|
||||
;;
|
||||
@@ -78,6 +81,10 @@ if [ $OS == 'Mac' ]; then
|
||||
|
||||
if [ "$CHANNEL" == 'beta' ]; then
|
||||
ATOM_EXECUTABLE_NAME="Atom Beta"
|
||||
elif [ "$CHANNEL" == 'nightly' ]; then
|
||||
ATOM_EXECUTABLE_NAME="Atom Nightly"
|
||||
elif [ "$CHANNEL" == 'dev' ]; then
|
||||
ATOM_EXECUTABLE_NAME="Atom Dev"
|
||||
else
|
||||
ATOM_EXECUTABLE_NAME="Atom"
|
||||
fi
|
||||
@@ -114,6 +121,9 @@ elif [ $OS == 'Linux' ]; then
|
||||
beta)
|
||||
ATOM_PATH="$USR_DIRECTORY/share/atom-beta/atom"
|
||||
;;
|
||||
nightly)
|
||||
ATOM_PATH="$USR_DIRECTORY/share/atom-nightly/atom"
|
||||
;;
|
||||
dev)
|
||||
ATOM_PATH="$USR_DIRECTORY/share/atom-dev/atom"
|
||||
;;
|
||||
|
||||
@@ -17,9 +17,8 @@ general:
|
||||
dependencies:
|
||||
pre:
|
||||
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash
|
||||
- nvm install 6.9.4
|
||||
- nvm use 6.9.4
|
||||
- npm install -g npm@5.3.0
|
||||
- nvm install 8.9.3
|
||||
- nvm use 8.9.3
|
||||
|
||||
override:
|
||||
- script/build --code-sign --compress-artifacts
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
Implemented in PR [#17538](https://github.com/atom/atom/pull/17538)
|
||||
|
||||
## Summary
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"electronVersion": "2.0.4",
|
||||
"electronVersion": "2.0.5",
|
||||
"dependencies": {
|
||||
"@atom/nsfw": "^1.0.18",
|
||||
"@atom/watcher": "1.0.3",
|
||||
@@ -91,7 +91,7 @@
|
||||
"one-light-syntax": "1.8.3",
|
||||
"solarized-dark-syntax": "1.1.5",
|
||||
"solarized-light-syntax": "1.1.5",
|
||||
"about": "1.9.1",
|
||||
"about": "1.10.0",
|
||||
"archive-view": "0.65.1",
|
||||
"autocomplete-atom-api": "0.10.7",
|
||||
"autocomplete-css": "0.17.5",
|
||||
@@ -111,7 +111,7 @@
|
||||
"exception-reporting": "0.43.1",
|
||||
"find-and-replace": "0.215.11",
|
||||
"fuzzy-finder": "1.8.2",
|
||||
"github": "0.17.2",
|
||||
"github": "0.17.3",
|
||||
"git-diff": "1.3.9",
|
||||
"go-to-line": "0.33.0",
|
||||
"grammar-selector": "0.50.1",
|
||||
@@ -127,7 +127,7 @@
|
||||
"package-generator": "1.3.0",
|
||||
"settings-view": "0.255.0",
|
||||
"snippets": "1.3.3",
|
||||
"spell-check": "0.73.5",
|
||||
"spell-check": "0.74.0",
|
||||
"status-bar": "1.8.15",
|
||||
"styleguide": "0.49.11",
|
||||
"symbols-view": "0.118.2",
|
||||
|
||||
BIN
resources/app-icons/nightly/atom.icns
Normal file
BIN
resources/app-icons/nightly/atom.ico
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
resources/app-icons/nightly/png/1024.png
Normal file
|
After Width: | Height: | Size: 348 KiB |
BIN
resources/app-icons/nightly/png/128.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
resources/app-icons/nightly/png/16.png
Normal file
|
After Width: | Height: | Size: 870 B |
BIN
resources/app-icons/nightly/png/24.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
resources/app-icons/nightly/png/256.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
resources/app-icons/nightly/png/32.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
resources/app-icons/nightly/png/48.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
resources/app-icons/nightly/png/512.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
resources/app-icons/nightly/png/64.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
@@ -104,8 +104,10 @@ if (!argv.generateApiDocs) {
|
||||
}
|
||||
if (argv.createWindowsInstaller) {
|
||||
return createWindowsInstaller(packagedAppPath)
|
||||
.then(() => argv.codeSign && codeSignOnWindows([ path.join(CONFIG.buildOutputPath, 'AtomSetup.exe') ]))
|
||||
.then(() => packagedAppPath)
|
||||
.then((installerPath) => {
|
||||
argv.codeSign && codeSignOnWindows([installerPath])
|
||||
return packagedAppPath
|
||||
})
|
||||
} else {
|
||||
console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer.'.gray)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const spawnSync = require('./lib/spawn-sync')
|
||||
|
||||
const repositoryRootPath = path.resolve(__dirname, '..')
|
||||
const apmRootPath = path.join(repositoryRootPath, 'apm')
|
||||
@@ -19,12 +20,16 @@ const atomHomeDirPath = process.env.ATOM_HOME || path.join(homeDirPath, '.atom')
|
||||
|
||||
const appMetadata = require(path.join(repositoryRootPath, 'package.json'))
|
||||
const apmMetadata = require(path.join(apmRootPath, 'package.json'))
|
||||
const channel = getChannel()
|
||||
const computedAppVersion = computeAppVersion(process.env.ATOM_RELEASE_VERSION || appMetadata.version)
|
||||
const channel = getChannel(computedAppVersion)
|
||||
const appName = getAppName(channel)
|
||||
|
||||
module.exports = {
|
||||
appMetadata,
|
||||
apmMetadata,
|
||||
channel,
|
||||
appName,
|
||||
computedAppVersion,
|
||||
repositoryRootPath,
|
||||
apmRootPath,
|
||||
scriptRootPath,
|
||||
@@ -40,14 +45,30 @@ module.exports = {
|
||||
snapshotAuxiliaryData: {}
|
||||
}
|
||||
|
||||
function getChannel () {
|
||||
if (appMetadata.version.match(/dev/)) {
|
||||
return 'dev'
|
||||
} else if (appMetadata.version.match(/beta/)) {
|
||||
return 'beta'
|
||||
} else {
|
||||
return 'stable'
|
||||
function getChannel (version) {
|
||||
const match = version.match(/\d+\.\d+\.\d+(-([a-z]+)(\d+|-\w{4,})?)?$/)
|
||||
if (!match) {
|
||||
throw new Error(`Found incorrectly formatted Atom version ${version}`)
|
||||
} else if (match[2]) {
|
||||
return match[2]
|
||||
}
|
||||
|
||||
return 'stable'
|
||||
}
|
||||
|
||||
function getAppName (channel) {
|
||||
return channel === 'stable'
|
||||
? 'Atom'
|
||||
: `Atom ${process.env.ATOM_CHANNEL_DISPLAY_NAME || channel.charAt(0).toUpperCase() + channel.slice(1)}`
|
||||
}
|
||||
|
||||
function computeAppVersion (version) {
|
||||
if (version.match(/-dev$/)) {
|
||||
const result = spawnSync('git', ['rev-parse', '--short', 'HEAD'], {cwd: repositoryRootPath})
|
||||
const commitHash = result.stdout.toString().trim()
|
||||
version += '-' + commitHash
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
function getApmBinPath () {
|
||||
|
||||
@@ -10,7 +10,7 @@ const path = require('path')
|
||||
|
||||
module.exports = function () {
|
||||
console.log('Deleting problematic package-lock.json files')
|
||||
let paths = glob.sync(path.join(CONFIG.repositoryRootPath, '**', 'package-lock.json'), {ignore: path.join('**', 'node_modules', '**')})
|
||||
let paths = glob.sync(path.join(CONFIG.repositoryRootPath, '**', 'package-lock.json'), {ignore: [path.join('**', 'node_modules', '**'), path.join('**', 'vsts', '**')]})
|
||||
|
||||
for (let path of paths) {
|
||||
fs.unlinkSync(path)
|
||||
|
||||
@@ -16,6 +16,36 @@ module.exports = function (packagedAppPath) {
|
||||
downloadFileFromGithub(process.env.ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL, certPath)
|
||||
}
|
||||
try {
|
||||
console.log(`Ensuring keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN} exists`)
|
||||
try {
|
||||
spawnSync('security', [
|
||||
'show-keychain-info',
|
||||
process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN
|
||||
], {stdio: 'inherit'})
|
||||
} catch (err) {
|
||||
console.log(`Creating keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN}`)
|
||||
// The keychain doesn't exist, try to create it
|
||||
spawnSync('security', [
|
||||
'create-keychain',
|
||||
'-p', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD,
|
||||
process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN
|
||||
], {stdio: 'inherit'})
|
||||
|
||||
// List the keychain to "activate" it. Somehow this seems
|
||||
// to be needed otherwise the signing operation fails
|
||||
spawnSync('security', [
|
||||
'list-keychains',
|
||||
'-s', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN
|
||||
], {stdio: 'inherit'})
|
||||
|
||||
// Make sure it doesn't time out before we use it
|
||||
spawnSync('security', [
|
||||
'set-keychain-settings',
|
||||
'-t', '3600',
|
||||
'-u', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN
|
||||
], {stdio: 'inherit'})
|
||||
}
|
||||
|
||||
console.log(`Unlocking keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN}`)
|
||||
const unlockArgs = ['unlock-keychain']
|
||||
// For signing on local workstations, password could be entered interactively
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const spawnSync = require('./spawn-sync')
|
||||
const { path7za } = require('7zip-bin')
|
||||
|
||||
const CONFIG = require('../config')
|
||||
|
||||
@@ -19,7 +20,7 @@ module.exports = function (packagedAppPath) {
|
||||
function getArchiveName () {
|
||||
switch (process.platform) {
|
||||
case 'darwin': return 'atom-mac.zip'
|
||||
case 'win32': return 'atom-windows.zip'
|
||||
case 'win32': return `atom-${process.arch === 'x64' ? 'x64-' : ''}windows.zip`
|
||||
default: return `atom-${getLinuxArchiveArch()}.tar.gz`
|
||||
}
|
||||
}
|
||||
@@ -44,7 +45,7 @@ function compress (inputDirPath, outputArchivePath) {
|
||||
compressCommand = 'zip'
|
||||
compressArguments = ['-r', '--symlinks']
|
||||
} else if (process.platform === 'win32') {
|
||||
compressCommand = '7z.exe'
|
||||
compressCommand = path7za
|
||||
compressArguments = ['a', '-r']
|
||||
} else {
|
||||
compressCommand = 'tar'
|
||||
|
||||
@@ -10,9 +10,8 @@ const CONFIG = require('../config')
|
||||
|
||||
module.exports = function (packagedAppPath) {
|
||||
console.log(`Creating Debian package for "${packagedAppPath}"`)
|
||||
const atomExecutableName = CONFIG.channel === 'beta' ? 'atom-beta' : 'atom'
|
||||
const apmExecutableName = CONFIG.channel === 'beta' ? 'apm-beta' : 'apm'
|
||||
const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom'
|
||||
const atomExecutableName = CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}`
|
||||
const apmExecutableName = CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}`
|
||||
const appDescription = CONFIG.appMetadata.description
|
||||
const appVersion = CONFIG.appMetadata.version
|
||||
let arch
|
||||
@@ -88,7 +87,7 @@ module.exports = function (packagedAppPath) {
|
||||
console.log(`Writing desktop entry file into "${debianPackageApplicationsDirPath}"`)
|
||||
const desktopEntryTemplate = fs.readFileSync(path.join(CONFIG.repositoryRootPath, 'resources', 'linux', 'atom.desktop.in'))
|
||||
const desktopEntryContents = template(desktopEntryTemplate)({
|
||||
appName: appName,
|
||||
appName: CONFIG.appName,
|
||||
appFileName: atomExecutableName,
|
||||
description: appDescription,
|
||||
installDir: '/usr',
|
||||
|
||||
@@ -10,9 +10,9 @@ const CONFIG = require('../config')
|
||||
|
||||
module.exports = function (packagedAppPath) {
|
||||
console.log(`Creating rpm package for "${packagedAppPath}"`)
|
||||
const atomExecutableName = CONFIG.channel === 'beta' ? 'atom-beta' : 'atom'
|
||||
const apmExecutableName = CONFIG.channel === 'beta' ? 'apm-beta' : 'apm'
|
||||
const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom'
|
||||
const atomExecutableName = CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}`
|
||||
const apmExecutableName = CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}`
|
||||
const appName = CONFIG.appName
|
||||
const appDescription = CONFIG.appMetadata.description
|
||||
// RPM versions can't have dashes or tildes in them.
|
||||
// (Ref.: https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const electronInstaller = require('electron-winstaller')
|
||||
const fs = require('fs-extra')
|
||||
const fs = require('fs')
|
||||
const glob = require('glob')
|
||||
const path = require('path')
|
||||
|
||||
@@ -16,17 +16,31 @@ module.exports = (packagedAppPath) => {
|
||||
loadingGif: path.join(CONFIG.repositoryRootPath, 'resources', 'win', 'loading.gif'),
|
||||
outputDirectory: CONFIG.buildOutputPath,
|
||||
noMsi: true,
|
||||
remoteReleases: `https://atom.io/api/updates${archSuffix}?version=${CONFIG.appMetadata.version}`,
|
||||
remoteReleases: `https://atom.io/api/updates${archSuffix}?version=${CONFIG.computedAppVersion}`,
|
||||
setupExe: `AtomSetup${process.arch === 'x64' ? '-x64' : ''}.exe`,
|
||||
setupIcon: path.join(CONFIG.repositoryRootPath, 'resources', 'app-icons', CONFIG.channel, 'atom.ico')
|
||||
}
|
||||
|
||||
const cleanUp = () => {
|
||||
for (let nupkgPath of glob.sync(`${CONFIG.buildOutputPath}/*.nupkg`)) {
|
||||
const releasesPath = `${CONFIG.buildOutputPath}/RELEASES`
|
||||
if (process.arch === 'x64' && fs.existsSync(releasesPath)) {
|
||||
fs.renameSync(releasesPath, `${releasesPath}-x64`)
|
||||
}
|
||||
|
||||
for (let nupkgPath of glob.sync(`${CONFIG.buildOutputPath}/atom-*.nupkg`)) {
|
||||
if (!nupkgPath.includes(CONFIG.appMetadata.version)) {
|
||||
console.log(`Deleting downloaded nupkg for previous version at ${nupkgPath} to prevent it from being stored as an artifact`)
|
||||
fs.removeSync(nupkgPath)
|
||||
fs.unlinkSync(nupkgPath)
|
||||
} else {
|
||||
if (process.arch === 'x64') {
|
||||
// Use the original .nupkg filename to generate the `atom-x64` name by inserting `-x64` after `atom`
|
||||
const newNupkgPath = nupkgPath.replace('atom-', 'atom-x64-')
|
||||
fs.renameSync(nupkgPath, newNupkgPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return `${CONFIG.buildOutputPath}/${options.setupExe}`
|
||||
}
|
||||
|
||||
console.log(`Creating Windows Installer for ${packagedAppPath}`)
|
||||
|
||||
@@ -6,7 +6,6 @@ const fs = require('fs-plus')
|
||||
const normalizePackageData = require('normalize-package-data')
|
||||
const path = require('path')
|
||||
const semver = require('semver')
|
||||
const spawnSync = require('./spawn-sync')
|
||||
|
||||
const CONFIG = require('../config')
|
||||
|
||||
@@ -16,7 +15,7 @@ module.exports = function () {
|
||||
CONFIG.appMetadata._atomMenu = buildPlatformMenuMetadata()
|
||||
CONFIG.appMetadata._atomKeymaps = buildPlatformKeymapsMetadata()
|
||||
CONFIG.appMetadata._deprecatedPackages = deprecatedPackagesMetadata
|
||||
CONFIG.appMetadata.version = computeAppVersion()
|
||||
CONFIG.appMetadata.version = CONFIG.computedAppVersion
|
||||
checkDeprecatedPackagesMetadata()
|
||||
fs.writeFileSync(path.join(CONFIG.intermediateAppPath, 'package.json'), JSON.stringify(CONFIG.appMetadata))
|
||||
}
|
||||
@@ -162,13 +161,3 @@ function checkDeprecatedPackagesMetadata () {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function computeAppVersion () {
|
||||
let version = CONFIG.appMetadata.version
|
||||
if (CONFIG.channel === 'dev') {
|
||||
const result = spawnSync('git', ['rev-parse', '--short', 'HEAD'], {cwd: CONFIG.repositoryRootPath})
|
||||
const commitHash = result.stdout.toString().trim()
|
||||
version += '-' + commitHash
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ module.exports = function (packagedAppPath) {
|
||||
const verifySnapshotScriptPath = path.join(CONFIG.repositoryRootPath, 'script', 'verify-snapshot-script')
|
||||
let nodeBundledInElectronPath
|
||||
if (process.platform === 'darwin') {
|
||||
const executableName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom'
|
||||
const executableName = CONFIG.appName
|
||||
nodeBundledInElectronPath = path.join(packagedAppPath, 'Contents', 'MacOS', executableName)
|
||||
} else if (process.platform === 'win32') {
|
||||
nodeBundledInElectronPath = path.join(packagedAppPath, 'atom.exe')
|
||||
|
||||
@@ -114,7 +114,7 @@ function buildAsarUnpackGlobExpression () {
|
||||
|
||||
function getAppName () {
|
||||
if (process.platform === 'darwin') {
|
||||
return CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom'
|
||||
return CONFIG.appName
|
||||
} else {
|
||||
return 'atom'
|
||||
}
|
||||
@@ -156,7 +156,7 @@ function renamePackagedAppDir (packageOutputDirPath) {
|
||||
if (fs.existsSync(packagedAppPath)) fs.removeSync(packagedAppPath)
|
||||
fs.renameSync(path.join(packageOutputDirPath, appBundleName), packagedAppPath)
|
||||
} else if (process.platform === 'linux') {
|
||||
const appName = CONFIG.channel === 'beta' ? 'atom-beta' : 'atom'
|
||||
const appName = CONFIG.channel !== 'stable' ? `atom-${CONFIG.channel}` : 'atom'
|
||||
let architecture
|
||||
if (process.arch === 'ia32') {
|
||||
architecture = 'i386'
|
||||
@@ -169,8 +169,7 @@ function renamePackagedAppDir (packageOutputDirPath) {
|
||||
if (fs.existsSync(packagedAppPath)) fs.removeSync(packagedAppPath)
|
||||
fs.renameSync(packageOutputDirPath, packagedAppPath)
|
||||
} else {
|
||||
const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom'
|
||||
packagedAppPath = path.join(CONFIG.buildOutputPath, appName)
|
||||
packagedAppPath = path.join(CONFIG.buildOutputPath, CONFIG.appName)
|
||||
if (process.platform === 'win32' && process.arch !== 'ia32') {
|
||||
packagedAppPath += ` ${process.arch}`
|
||||
}
|
||||
|
||||
57
script/lib/upload-to-s3.js
Normal file
@@ -0,0 +1,57 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const aws = require('aws-sdk')
|
||||
|
||||
module.exports = function (s3Key, s3Secret, s3Bucket, directory, assets) {
|
||||
const s3 = new aws.S3({
|
||||
accessKeyId: s3Key,
|
||||
secretAccessKey: s3Secret,
|
||||
params: { Bucket: s3Bucket }
|
||||
})
|
||||
|
||||
function listExistingAssetsForDirectory (directory) {
|
||||
return s3.listObjectsV2({ Prefix: directory }).promise().then((res) => {
|
||||
return res.Contents.map((obj) => { return { Key: obj.Key } })
|
||||
})
|
||||
}
|
||||
|
||||
function deleteExistingAssets (existingAssets) {
|
||||
if (existingAssets.length > 0) {
|
||||
return s3.deleteObjects({ Delete: { Objects: existingAssets } }).promise()
|
||||
} else {
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
}
|
||||
|
||||
function uploadAssets (assets, directory) {
|
||||
return assets.reduce(
|
||||
function (promise, asset) {
|
||||
return promise.then(() => uploadAsset(directory, asset))
|
||||
}, Promise.resolve())
|
||||
}
|
||||
|
||||
function uploadAsset (directory, assetPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.info(`Uploading ${assetPath}`)
|
||||
const params = {
|
||||
Key: `${directory}${path.basename(assetPath)}`,
|
||||
ACL: 'public-read',
|
||||
Body: fs.createReadStream(assetPath)
|
||||
}
|
||||
|
||||
s3.upload(params, error => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return listExistingAssetsForDirectory(directory)
|
||||
.then(deleteExistingAssets)
|
||||
.then(() => uploadAssets(assets, directory))
|
||||
}
|
||||
@@ -2,7 +2,9 @@
|
||||
"name": "atom-build-scripts",
|
||||
"description": "Atom build scripts",
|
||||
"dependencies": {
|
||||
"7zip-bin": "^4.0.2",
|
||||
"async": "2.0.1",
|
||||
"aws-sdk": "^2.5.2",
|
||||
"babel-core": "5.8.38",
|
||||
"coffeelint": "1.15.7",
|
||||
"colors": "1.1.2",
|
||||
@@ -26,6 +28,7 @@
|
||||
"npm": "5.3.0",
|
||||
"passwd-user": "2.1.0",
|
||||
"pegjs": "0.9.0",
|
||||
"publish-release": "^1.6.0",
|
||||
"random-seed": "^0.3.0",
|
||||
"season": "5.3.0",
|
||||
"semver": "5.3.0",
|
||||
|
||||
52
script/publish-release
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const glob = require('glob')
|
||||
const publishRelease = require('publish-release')
|
||||
const uploadToS3 = require('./lib/upload-to-s3')
|
||||
const CONFIG = require('./config')
|
||||
|
||||
const yargs = require('yargs')
|
||||
const argv = yargs
|
||||
.usage('Usage: $0 [options]')
|
||||
.help('help')
|
||||
.describe('assets-path', 'Path to the folder where all release assets are stored')
|
||||
.wrap(yargs.terminalWidth())
|
||||
.argv
|
||||
|
||||
let assetsPath = argv.assetsPath || path.join(CONFIG.repositoryRootPath, 'out')
|
||||
let assets = glob.sync(path.join(assetsPath, '*(*.exe|*.zip|*.nupkg|*.tar.gz|*.rpm|*.deb|RELEASES*)'))
|
||||
|
||||
console.log(`Uploading release assets for ${CONFIG.computedAppVersion} to S3`)
|
||||
|
||||
uploadToS3(
|
||||
process.env.ATOM_RELEASES_S3_KEY,
|
||||
process.env.ATOM_RELEASES_S3_SECRET,
|
||||
process.env.ATOM_RELEASES_S3_BUCKET,
|
||||
`releases/v${CONFIG.computedAppVersion}/`,
|
||||
assets).then(
|
||||
() => {
|
||||
console.log(`Publishing GitHub release ${CONFIG.computedAppVersion}`)
|
||||
publishRelease({
|
||||
token: process.env.GITHUB_TOKEN,
|
||||
owner: 'atom',
|
||||
repo: CONFIG.channel !== 'nightly' ? 'atom' : 'atom-nightly-releases',
|
||||
name: CONFIG.computedAppVersion,
|
||||
tag: `v${CONFIG.computedAppVersion}`,
|
||||
draft: false,
|
||||
prerelease: CONFIG.channel !== 'stable',
|
||||
reuseRelease: true,
|
||||
skipIfPublished: true,
|
||||
assets
|
||||
}, function (err, release) {
|
||||
if (err) {
|
||||
console.error("An error occurred while publishing the release:\n\n", err)
|
||||
} else {
|
||||
console.log("Release published successfully: ", release.html_url)
|
||||
}
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.error('An error occurred while uploading the release:', err)
|
||||
})
|
||||
5
script/publish-release.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
@IF EXIST "%~dp0\node.exe" (
|
||||
"%~dp0\node.exe" "%~dp0\publish-release" %*
|
||||
) ELSE (
|
||||
node "%~dp0\publish-release" %*
|
||||
)
|
||||
65
script/vsts/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Atom Release Build Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This folder contains build configuration and scripts for automating Atom's
|
||||
release pipeline using [Visual Studio Team Services](https://azure.microsoft.com/en-us/services/visual-studio-team-services/).
|
||||
VSTS allows us to leverage [multi-phase jobs](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-jobs.md) to generate Atom installation packages
|
||||
on Windows, macOS, and Linux and then publish a new release automatically once
|
||||
the build completes successfully.
|
||||
|
||||
## Nightly Release Build
|
||||
|
||||
Our scheduled nightly release uses a mutli-phase job to automatically generate Atom
|
||||
Nightly installation packages and then publish them to GitHub and atom.io.
|
||||
|
||||
The [Atom Nightly build definition](https://github.visualstudio.com/Atom/_build/index?context=mine&path=%5C&definitionId=1&_a=completed)
|
||||
is configured with the [`nightly-release.yml`](nightly-release.yml) file. More
|
||||
information on VSTS' YAML configuration format can be found in their [Getting Started](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md)
|
||||
documentation.
|
||||
|
||||
### Versioning Phase
|
||||
|
||||
In this phase, we run [`script/vsts/generate-version.js`](generate-version.js) to
|
||||
determine the version of the next Atom Nightly release. This script consults the
|
||||
GitHub v3 API to get the list of releases on the [`atom/atom-nightly-releases`](https://github.com/atom/atom-nightly-releases)
|
||||
repo. We look for the most recent, non-draft release and then parse its version
|
||||
number (e.g. `1.30.0-nightly4`) to extract the base version and the monotonically-increasing
|
||||
nightly release number.
|
||||
|
||||
Once we have the version and release number, we compare the base version number
|
||||
(`1.30.0`) against the one in `package.json` of the latest commit in the local
|
||||
repo. If those versions are the same, we increment the release number (`1.30.0-nightly5`).
|
||||
If those versions are different, we use `0` for the release number to start a
|
||||
new series of Nightly releases for the new version (`1.31.0-nightly0`).
|
||||
|
||||
Once the release version has been determined, it is set as our custom `ReleaseVersion`
|
||||
[output variable](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-outputvariables.md)
|
||||
by writing out a special string to `stdout` which is recognized by VSTS. This
|
||||
variable will be used in later build steps.
|
||||
|
||||
If any part of the build process fails from this point forward, the same version
|
||||
number *should* be chosen in the next build unless the base version number has
|
||||
been changed in `master`.
|
||||
|
||||
### OS-specific Build Phases
|
||||
|
||||
In this part of the build, we use [phase templates](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md)
|
||||
for [Windows](windows.yml), [macOS](macos.yml), and [Linux](linux.yml) to build
|
||||
Atom simultaneously across those platforms and then run the Atom test suite to
|
||||
verify the builds. If build, test, and linting come back clean, we take the build
|
||||
assets generated in the `out` folder on each OS and then stage them as build artifacts.
|
||||
|
||||
For each OS build, we refer to the `ReleaseVersion` variable, set in the previous
|
||||
phase, to configure the `ATOM_RELEASE_VERSION` environment variable to override
|
||||
the version contained in Atom's `package.json`.
|
||||
|
||||
### Publish Phase
|
||||
|
||||
If all three OS builds have completed successfully, the publish phase will launch the
|
||||
[`script/publish-release`](../publish-release) script to collect the release
|
||||
artifacts created from those builds and then upload them to the S3 bucket from
|
||||
which Atom release assets are served. If the upload process is successful, a new
|
||||
release will be created on the `atom/atom-nightly-releases` repo using the
|
||||
`ReleaseVersion` with a `v` prefix as the tag name. The release assets will also
|
||||
be uploaded to the GitHub release at this time.
|
||||
33
script/vsts/generate-version.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const path = require('path')
|
||||
const request = require('request-promise-native')
|
||||
|
||||
const repositoryRootPath = path.resolve(__dirname, '..', '..')
|
||||
const appMetadata = require(path.join(repositoryRootPath, 'package.json'))
|
||||
const baseVersion = appMetadata.version.split('-')[0]
|
||||
|
||||
async function generateNightlyVersion () {
|
||||
const releases = await request({
|
||||
url: 'https://api.github.com/repos/atom/atom-nightly-releases/releases',
|
||||
headers: {'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'Atom Release Build'},
|
||||
json: true
|
||||
})
|
||||
|
||||
let releaseNumber = 0
|
||||
if (releases && releases.length > 0) {
|
||||
const latestRelease = releases.find(r => !r.draft)
|
||||
const versionMatch = latestRelease.tag_name.match(/^v?(\d+\.\d+\.\d+)-nightly(\d+)$/)
|
||||
|
||||
if (versionMatch && versionMatch[1] === baseVersion) {
|
||||
releaseNumber = parseInt(versionMatch[2]) + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Set our ReleaseVersion build variable and update VSTS' build number to
|
||||
// include the version. Writing these strings to stdout causes VSTS to set
|
||||
// the associated variables.
|
||||
const generatedVersion = `${baseVersion}-nightly${releaseNumber}`
|
||||
console.log(`##vso[task.setvariable variable=ReleaseVersion;isOutput=true]${generatedVersion}`)
|
||||
console.log(`##vso[build.updatebuildnumber]${generatedVersion}+${process.env.BUILD_BUILDNUMBER}`)
|
||||
}
|
||||
|
||||
generateNightlyVersion()
|
||||
58
script/vsts/linux.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
phases:
|
||||
- phase: Linux
|
||||
dependsOn: GetReleaseVersion
|
||||
variables:
|
||||
ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ]
|
||||
queue:
|
||||
name: Hosted Linux Preview
|
||||
timeoutInMinutes: 180
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: 8.9.3
|
||||
displayName: Install Node.js 8.9.3
|
||||
|
||||
- script: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends build-essential xvfb clang-3.5 fakeroot git libsecret-1-dev rpm libx11-dev libxkbfile-dev xz-utils xorriso zsync libxss1 libgconf2-4 libgtk-3-0
|
||||
displayName: Install apt dependencies
|
||||
|
||||
- script: |
|
||||
script/build --create-debian-package --create-rpm-package --compress-artifacts
|
||||
env:
|
||||
ATOM_RELEASE_VERSION: $(ReleaseVersion)
|
||||
displayName: Build Atom
|
||||
|
||||
- script: script/lint
|
||||
displayName: Run linter
|
||||
|
||||
- script: |
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
|
||||
export DISPLAY=':99.0'
|
||||
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||
script/test
|
||||
env:
|
||||
CI: true
|
||||
CI_PROVIDER: VSTS
|
||||
displayName: Run tests
|
||||
|
||||
# This step is necessary in the short term due to a bug in the *NIX
|
||||
# implementation of the CopyFiles task which scans the entire file
|
||||
# system structure just to resolve the glob pattern.
|
||||
- script: rm -rf $(Build.SourcesDirectory)/out/*/
|
||||
displayName: Delete Intermediate Output
|
||||
|
||||
- task: CopyFiles@2
|
||||
inputs:
|
||||
sourceFolder: $(Build.SourcesDirectory)/out
|
||||
contents: '?(*.deb|*.rpm|*.tar.gz)'
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Stage Artifacts
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)
|
||||
ArtifactName: Binaries
|
||||
ArtifactType: Container
|
||||
displayName: Upload Artifacts
|
||||
55
script/vsts/macos.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
phases:
|
||||
- phase: macOS
|
||||
dependsOn: GetReleaseVersion
|
||||
variables:
|
||||
ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ]
|
||||
queue:
|
||||
name: Hosted macOS Preview
|
||||
timeoutInMinutes: 180
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: 8.9.3
|
||||
displayName: Install Node.js 8.9.3
|
||||
|
||||
- script: |
|
||||
script/build --code-sign --compress-artifacts
|
||||
displayName: Build Atom
|
||||
env:
|
||||
ATOM_RELEASE_VERSION: $(ReleaseVersion)
|
||||
ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL: $(ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL)
|
||||
ATOM_MAC_CODE_SIGNING_CERT_PASSWORD: $(ATOM_MAC_CODE_SIGNING_CERT_PASSWORD)
|
||||
ATOM_MAC_CODE_SIGNING_KEYCHAIN: $(ATOM_MAC_CODE_SIGNING_KEYCHAIN)
|
||||
ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD: $(ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD)
|
||||
|
||||
- script: script/lint
|
||||
displayName: Run linter
|
||||
|
||||
- script: |
|
||||
osascript -e 'tell application "System Events" to keystroke "x"' # clear screen saver
|
||||
caffeinate -s script/test # Run with caffeinate to prevent screen saver
|
||||
env:
|
||||
CI: true
|
||||
CI_PROVIDER: VSTS
|
||||
displayName: Run tests
|
||||
|
||||
# This step is necessary in the short term due to a bug in the *NIX
|
||||
# implementation of the CopyFiles task which scans the entire file
|
||||
# system structure just to resolve the glob pattern.
|
||||
- script: rm -rf $(Build.SourcesDirectory)/out/*/
|
||||
displayName: Delete Intermediate Output
|
||||
|
||||
- task: CopyFiles@2
|
||||
inputs:
|
||||
sourceFolder: $(Build.SourcesDirectory)/out
|
||||
contents: '*.zip'
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Stage Artifacts
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)
|
||||
ArtifactName: Binaries
|
||||
ArtifactType: Container
|
||||
displayName: Upload Artifacts
|
||||
57
script/vsts/nightly-release.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
phases:
|
||||
|
||||
- phase: GetReleaseVersion
|
||||
steps:
|
||||
# This has to be done separately because VSTS inexplicably
|
||||
# exits the script block after `npm install` completes.
|
||||
- script: |
|
||||
cd script\vsts
|
||||
npm install
|
||||
displayName: npm install
|
||||
- script: node script\vsts\generate-version.js
|
||||
name: Version
|
||||
|
||||
# Import OS-specific build definitions
|
||||
- template: windows.yml
|
||||
- template: macos.yml
|
||||
- template: linux.yml
|
||||
|
||||
- phase: Release
|
||||
queue: Hosted # Need this for Python 2.7
|
||||
|
||||
dependsOn:
|
||||
- GetReleaseVersion
|
||||
- Windows
|
||||
- Linux
|
||||
- macOS
|
||||
|
||||
variables:
|
||||
ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ]
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: 8.9.3
|
||||
displayName: Install Node.js 8.9.3
|
||||
|
||||
# This has to be done separately because VSTS inexplicably
|
||||
# exits the script block after `npm install` completes.
|
||||
- script: |
|
||||
cd script
|
||||
npm install
|
||||
displayName: npm install
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Release Artifacts
|
||||
inputs:
|
||||
artifactName: Binaries
|
||||
|
||||
- script: |
|
||||
$(Build.SourcesDirectory)\script\publish-release.cmd --assets-path "$(System.ArtifactsDirectory)/Binaries"
|
||||
env:
|
||||
GITHUB_TOKEN: $(GITHUB_TOKEN)
|
||||
ATOM_RELEASE_VERSION: $(ReleaseVersion)
|
||||
ATOM_RELEASES_S3_KEY: $(ATOM_RELEASES_S3_KEY)
|
||||
ATOM_RELEASES_S3_SECRET: $(ATOM_RELEASES_S3_SECRET)
|
||||
ATOM_RELEASES_S3_BUCKET: $(ATOM_RELEASES_S3_BUCKET)
|
||||
displayName: Create Nightly Release
|
||||
357
script/vsts/package-lock.json
generated
Normal file
@@ -0,0 +1,357 @@
|
||||
{
|
||||
"name": "atom-release-scripts",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"requires": {
|
||||
"co": "4.6.0",
|
||||
"fast-deep-equal": "1.1.0",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"json-schema-traverse": "0.3.1"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
|
||||
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
|
||||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"requires": {
|
||||
"delayed-stream": "1.0.0"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "0.1.1"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
||||
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"requires": {
|
||||
"asynckit": "0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"mime-types": "2.1.18"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"requires": {
|
||||
"ajv": "5.5.2",
|
||||
"har-schema": "2.0.0"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"jsprim": "1.4.1",
|
||||
"sshpk": "1.14.2"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.10",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.18",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.33.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"request": {
|
||||
"version": "2.87.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
|
||||
"integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
|
||||
"requires": {
|
||||
"aws-sign2": "0.7.0",
|
||||
"aws4": "1.7.0",
|
||||
"caseless": "0.12.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"extend": "3.0.1",
|
||||
"forever-agent": "0.6.1",
|
||||
"form-data": "2.3.2",
|
||||
"har-validator": "5.0.3",
|
||||
"http-signature": "1.2.0",
|
||||
"is-typedarray": "1.0.0",
|
||||
"isstream": "0.1.2",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"mime-types": "2.1.18",
|
||||
"oauth-sign": "0.8.2",
|
||||
"performance-now": "2.1.0",
|
||||
"qs": "6.5.2",
|
||||
"safe-buffer": "5.1.2",
|
||||
"tough-cookie": "2.3.4",
|
||||
"tunnel-agent": "0.6.0",
|
||||
"uuid": "3.3.0"
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
|
||||
"integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
|
||||
"requires": {
|
||||
"lodash": "4.17.10"
|
||||
}
|
||||
},
|
||||
"request-promise-native": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz",
|
||||
"integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=",
|
||||
"requires": {
|
||||
"request-promise-core": "1.1.1",
|
||||
"stealthy-require": "1.1.1",
|
||||
"tough-cookie": "2.3.4"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
||||
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
|
||||
"requires": {
|
||||
"asn1": "0.2.3",
|
||||
"assert-plus": "1.0.0",
|
||||
"bcrypt-pbkdf": "1.0.1",
|
||||
"dashdash": "1.14.1",
|
||||
"ecc-jsbn": "0.1.1",
|
||||
"getpass": "0.1.7",
|
||||
"jsbn": "0.1.1",
|
||||
"safer-buffer": "2.1.2",
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"stealthy-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
|
||||
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
||||
"requires": {
|
||||
"punycode": "1.4.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.0.tgz",
|
||||
"integrity": "sha512-ijO9N2xY/YaOqQ5yz5c4sy2ZjWmA6AR6zASb/gdpeKZ8+948CxwfMW9RrKVk5may6ev8c0/Xguu32e2Llelpqw=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "1.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
script/vsts/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "atom-release-scripts",
|
||||
"description": "Atom release scripts",
|
||||
"dependencies": {
|
||||
"request": "^2.87.0",
|
||||
"request-promise-native": "^1.0.5"
|
||||
}
|
||||
}
|
||||
54
script/vsts/windows.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
phases:
|
||||
- phase: Windows
|
||||
dependsOn: GetReleaseVersion
|
||||
variables:
|
||||
ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ]
|
||||
queue:
|
||||
name: Hosted
|
||||
timeoutInMinutes: 180
|
||||
parallel: 2
|
||||
matrix:
|
||||
x64:
|
||||
buildArch: x64
|
||||
# TODO: x86 is currently not supported on VSTS
|
||||
# x86:
|
||||
# buildArch: x86
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: 8.9.3
|
||||
displayName: Install Node.js 8.9.3
|
||||
|
||||
- script: |
|
||||
IF NOT EXIST C:\tmp MKDIR C:\tmp
|
||||
SET SQUIRREL_TEMP=C:\tmp
|
||||
script\build.cmd --create-windows-installer --code-sign --compress-artifacts
|
||||
env:
|
||||
ATOM_RELEASE_VERSION: $(ReleaseVersion)
|
||||
ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL: $(ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL)
|
||||
ATOM_WIN_CODE_SIGNING_CERT_PASSWORD: $(ATOM_WIN_CODE_SIGNING_CERT_PASSWORD)
|
||||
displayName: Build Atom
|
||||
|
||||
- script: script\lint.cmd
|
||||
displayName: Run linter
|
||||
|
||||
- script: script\test.cmd
|
||||
env:
|
||||
CI: true
|
||||
CI_PROVIDER: VSTS
|
||||
displayName: Run tests
|
||||
|
||||
- task: CopyFiles@2
|
||||
inputs:
|
||||
sourceFolder: $(Build.SourcesDirectory)/out
|
||||
contents: '?(*.exe|*.zip|*.nupkg|RELEASES*)'
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Stage Artifacts
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)
|
||||
ArtifactName: Binaries
|
||||
ArtifactType: Container
|
||||
displayName: Upload Artifacts
|
||||
@@ -1,6 +1,7 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs-plus')
|
||||
const temp = require('temp').track()
|
||||
const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./async-spec-helpers');
|
||||
const CommandInstaller = require('../src/command-installer')
|
||||
|
||||
describe('CommandInstaller on #darwin', () => {
|
||||
@@ -56,8 +57,8 @@ describe('CommandInstaller on #darwin', () => {
|
||||
const appDelegate = jasmine.createSpyObj('appDelegate', ['confirm'])
|
||||
installer = new CommandInstaller(appDelegate)
|
||||
installer.initialize('2.0.2')
|
||||
spyOn(installer, 'installAtomCommand').andCallFake((__, callback) => callback())
|
||||
spyOn(installer, 'installApmCommand').andCallFake((__, callback) => callback())
|
||||
spyOn(installer, 'installAtomCommand').andCallFake((__, callback) => callback(undefined, 'atom'))
|
||||
spyOn(installer, 'installApmCommand').andCallFake((__, callback) => callback(undefined, 'apm'))
|
||||
|
||||
installer.installShellCommandsInteractively()
|
||||
|
||||
@@ -140,4 +141,41 @@ describe('CommandInstaller on #darwin', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when using a nightly version of atom', () => {
|
||||
beforeEach(() => {
|
||||
installer = new CommandInstaller()
|
||||
installer.initialize('2.2.0-nightly0')
|
||||
})
|
||||
|
||||
it("symlinks the atom command as 'atom-nightly'", () => {
|
||||
const installedAtomPath = path.join(installationPath, 'atom-nightly')
|
||||
expect(fs.isFileSync(installedAtomPath)).toBeFalsy()
|
||||
|
||||
waitsFor(done => {
|
||||
installer.installAtomCommand(false, error => {
|
||||
expect(error).toBeNull()
|
||||
expect(fs.realpathSync(installedAtomPath)).toBe(fs.realpathSync(atomBinPath))
|
||||
expect(fs.isExecutableSync(installedAtomPath)).toBe(true)
|
||||
expect(fs.isFileSync(path.join(installationPath, 'atom'))).toBe(false)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("symlinks the apm command as 'apm-nightly'", () => {
|
||||
const installedApmPath = path.join(installationPath, 'apm-nightly')
|
||||
expect(fs.isFileSync(installedApmPath)).toBeFalsy()
|
||||
|
||||
waitsFor(done => {
|
||||
installer.installApmCommand(false, error => {
|
||||
expect(error).toBeNull()
|
||||
expect(fs.realpathSync(installedApmPath)).toBe(fs.realpathSync(apmBinPath))
|
||||
expect(fs.isExecutableSync(installedApmPath)).toBeTruthy()
|
||||
expect(fs.isFileSync(path.join(installationPath, 'nightly'))).toBe(false)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const {dialog} = require('electron')
|
||||
const FileRecoveryService = require('../../src/main-process/file-recovery-service')
|
||||
const fs = require('fs-plus')
|
||||
const fsreal = require('fs')
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const sinon = require('sinon')
|
||||
const {escapeRegExp} = require('underscore-plus')
|
||||
const temp = require('temp').track()
|
||||
@@ -116,13 +118,22 @@ describe("FileRecoveryService", () => {
|
||||
const mockWindow = {}
|
||||
const filePath = temp.path()
|
||||
fs.writeFileSync(filePath, "content")
|
||||
fs.chmodSync(filePath, 0444)
|
||||
|
||||
let logs = []
|
||||
spies.stub(console, 'log', (message) => logs.push(message))
|
||||
spies.stub(dialog, 'showMessageBox')
|
||||
|
||||
// Copy files to be recovered before mocking fs.createWriteStream
|
||||
await recoveryService.willSavePath(mockWindow, filePath)
|
||||
|
||||
// Stub out fs.createWriteStream so that we can return a fake error when
|
||||
// attempting to copy the recovered file to its original location
|
||||
var fakeEmitter = new EventEmitter()
|
||||
var onStub = spies.stub(fakeEmitter, 'on')
|
||||
onStub.withArgs('error').yields(new Error('Nope')).returns(fakeEmitter)
|
||||
onStub.withArgs('open').returns(fakeEmitter)
|
||||
spies.stub(fsreal, 'createWriteStream').withArgs(filePath).returns(fakeEmitter)
|
||||
|
||||
await recoveryService.didCrashWindow(mockWindow)
|
||||
let recoveryFiles = fs.listTreeSync(recoveryDirectory)
|
||||
assert.equal(recoveryFiles.length, 1)
|
||||
|
||||
@@ -212,6 +212,18 @@ describe('TooltipManager', () => {
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
describe('when a user types', () =>
|
||||
it('hides the tooltips', () => {
|
||||
const disposable = manager.add(element, { title: 'Title' })
|
||||
hover(element, function () {
|
||||
expect(document.body.querySelector('.tooltip')).not.toBeNull()
|
||||
window.dispatchEvent(new CustomEvent('keydown'))
|
||||
expect(document.body.querySelector('.tooltip')).toBeNull()
|
||||
disposable.dispose()
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
describe('findTooltips', () => {
|
||||
it('adds and remove tooltips correctly', () => {
|
||||
|
||||
@@ -487,21 +487,25 @@ class AtomEnvironment {
|
||||
|
||||
// Public: Gets the release channel of the Atom application.
|
||||
//
|
||||
// Returns the release channel as a {String}. Will return one of `dev`, `beta`, or `stable`.
|
||||
// Returns the release channel as a {String}. Will return a specific release channel
|
||||
// name like 'beta' or 'nightly' if one is found in the Atom version or 'stable'
|
||||
// otherwise.
|
||||
getReleaseChannel () {
|
||||
const version = this.getVersion()
|
||||
if (version.includes('beta')) {
|
||||
return 'beta'
|
||||
} else if (version.includes('dev')) {
|
||||
return 'dev'
|
||||
} else {
|
||||
return 'stable'
|
||||
// This matches stable, dev (with or without commit hash) and any other
|
||||
// release channel following the pattern '1.00.0-channel0'
|
||||
const match = this.getVersion().match(/\d+\.\d+\.\d+(-([a-z]+)(\d+|-\w{4,})?)?$/)
|
||||
if (!match) {
|
||||
return 'unrecognized'
|
||||
} else if (match[2]) {
|
||||
return match[2]
|
||||
}
|
||||
|
||||
return 'stable'
|
||||
}
|
||||
|
||||
// Public: Returns a {Boolean} that is `true` if the current version is an official release.
|
||||
isReleasedVersion () {
|
||||
return !/\w{7}/.test(this.getVersion()) // Check if the release is a 7-character SHA prefix
|
||||
return this.getReleaseChannel().match(/stable|beta|nightly/) != null
|
||||
}
|
||||
|
||||
// Public: Get the time taken to completely load the current window.
|
||||
|
||||
@@ -27,22 +27,36 @@ class CommandInstaller {
|
||||
}, () => {})
|
||||
}
|
||||
|
||||
this.installAtomCommand(true, error => {
|
||||
this.installAtomCommand(true, (error, atomCommandName) => {
|
||||
if (error) return showErrorDialog(error)
|
||||
this.installApmCommand(true, error => {
|
||||
this.installApmCommand(true, (error, apmCommandName) => {
|
||||
if (error) return showErrorDialog(error)
|
||||
this.applicationDelegate.confirm({
|
||||
message: 'Commands installed.',
|
||||
detail: 'The shell commands `atom` and `apm` are installed.'
|
||||
detail: `The shell commands \`${atomCommandName}\` and \`${apmCommandName}\` are installed.`
|
||||
}, () => {})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getCommandNameForChannel (commandName) {
|
||||
let channelMatch = this.appVersion.match(/beta|nightly/)
|
||||
let channel = channelMatch ? channelMatch[0] : ''
|
||||
|
||||
switch (channel) {
|
||||
case 'beta':
|
||||
return `${commandName}-beta`
|
||||
case 'nightly':
|
||||
return `${commandName}-nightly`
|
||||
default:
|
||||
return commandName
|
||||
}
|
||||
}
|
||||
|
||||
installAtomCommand (askForPrivilege, callback) {
|
||||
this.installCommand(
|
||||
path.join(this.getResourcesDirectory(), 'app', 'atom.sh'),
|
||||
this.appVersion.includes('beta') ? 'atom-beta' : 'atom',
|
||||
this.getCommandNameForChannel('atom'),
|
||||
askForPrivilege,
|
||||
callback
|
||||
)
|
||||
@@ -51,7 +65,7 @@ class CommandInstaller {
|
||||
installApmCommand (askForPrivilege, callback) {
|
||||
this.installCommand(
|
||||
path.join(this.getResourcesDirectory(), 'app', 'apm', 'node_modules', '.bin', 'apm'),
|
||||
this.appVersion.includes('beta') ? 'apm-beta' : 'apm',
|
||||
this.getCommandNameForChannel('apm'),
|
||||
askForPrivilege,
|
||||
callback
|
||||
)
|
||||
@@ -64,11 +78,11 @@ class CommandInstaller {
|
||||
|
||||
fs.readlink(destinationPath, (error, realpath) => {
|
||||
if (error && error.code !== 'ENOENT') return callback(error)
|
||||
if (realpath === commandPath) return callback()
|
||||
if (realpath === commandPath) return callback(null, commandName)
|
||||
this.createSymlink(fs, commandPath, destinationPath, error => {
|
||||
if (error && error.code === 'EACCES' && askForPrivilege) {
|
||||
const fsAdmin = require('fs-admin')
|
||||
this.createSymlink(fsAdmin, commandPath, destinationPath, callback)
|
||||
this.createSymlink(fsAdmin, commandPath, destinationPath, (error) => { callback(error, commandName) })
|
||||
} else {
|
||||
callback(error)
|
||||
}
|
||||
|
||||
@@ -12,13 +12,18 @@ module.exports = function parseCommandLine (processArgs) {
|
||||
options.usage(
|
||||
dedent`Atom Editor v${version}
|
||||
|
||||
Usage: atom [options] [path ...]
|
||||
Usage:
|
||||
atom [options] [path ...]
|
||||
atom file[:line[:column]]
|
||||
|
||||
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.
|
||||
|
||||
A file may be opened at the desired line (and optionally column) by
|
||||
appending the numbers right after the file name, e.g. \`atom file:5:8\`.
|
||||
|
||||
Paths that start with \`atom://\` will be interpreted as URLs.
|
||||
|
||||
Environment Variables:
|
||||
|
||||
@@ -153,9 +153,11 @@ class TooltipManager {
|
||||
}
|
||||
|
||||
window.addEventListener('resize', hideTooltip)
|
||||
window.addEventListener('keydown', hideTooltip)
|
||||
|
||||
const disposable = new Disposable(() => {
|
||||
window.removeEventListener('resize', hideTooltip)
|
||||
window.removeEventListener('keydown', hideTooltip)
|
||||
hideTooltip()
|
||||
tooltip.destroy()
|
||||
|
||||
|
||||