mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-06 04:35:30 +08:00
feat(logging): Developer bar, verbose logging to logstash, Electron 0.26.0
Summary: - We now make verbose log files continuously as you use the app - We ship the logs to LogStash via S3 when an exception occurs - We log the DatabaseStore, ActionBridge and Analytics packages - We are now on the latest version of Electron 0.26.0 - We are now on Chrome 42 and io.js 1.4.3 - We should be setup to use ASAR soon. Update atom.sh to reflect that we're now electron oniguruma was unnecessary correctly find log files that haven't been shipped yet Fix a small issue with nodeIsVisible after upgrade to Chrome 42 Delete old logs, better logging from database store, don't ship empty logs Test Plan: Run existing tests Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D1531
This commit is contained in:
parent
f274bbbf30
commit
8599bc0397
64 changed files with 650 additions and 368 deletions
|
@ -6,6 +6,6 @@
|
|||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.135.0"
|
||||
"atom-package-manager": "0.167.0"
|
||||
}
|
||||
}
|
||||
|
|
18
atom.sh
18
atom.sh
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This file is sym-linked to the `atom` executable.
|
||||
# This file is sym-linked to the `electron` executable.
|
||||
# It is used by `apm` when calling commands.
|
||||
|
||||
if [ "$(uname)" == 'Darwin' ]; then
|
||||
|
@ -53,16 +53,16 @@ if [ $OS == 'Mac' ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
ATOM_SHELL_PATH=${ATOM_SHELL_PATH:-$EDGEHILL_PATH/atom-shell} # Set ATOM_SHELL_PATH unless it is already set
|
||||
ELECTRON_PATH=${ELECTRON_PATH:-$EDGEHILL_PATH/atom-shell} # Set ELECTRON_PATH unless it is already set
|
||||
|
||||
# Exit if Atom can't be found
|
||||
if [ -z "$ATOM_SHELL_PATH" ]; then
|
||||
echo "Cannot locate atom-shell. Be sure you have run script/grunt download-atom-shell first from $EDGEHILL_PATH"
|
||||
if [ -z "$ELECTRON_PATH" ]; then
|
||||
echo "Cannot locate electron. Be sure you have run script/grunt download-electron first from $EDGEHILL_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We find the atom-shell executable inside of the atom-shell directory.
|
||||
$ATOM_SHELL_PATH/Atom.app/Contents/MacOS/Atom --executed-from="$(pwd)" --pid=$$ "$@" $EDGEHILL_PATH
|
||||
$ELECTRON_PATH/Electron.app/Contents/MacOS/Electron --executed-from="$(pwd)" --pid=$$ "$@" $EDGEHILL_PATH
|
||||
|
||||
elif [ $OS == 'Linux' ]; then
|
||||
DOT_INBOX_DIR="$HOME/.nylas"
|
||||
|
@ -74,16 +74,16 @@ elif [ $OS == 'Linux' ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
ATOM_SHELL_PATH=${ATOM_SHELL_PATH:-$EDGEHILL_PATH/atom-shell} # Set ATOM_SHELL_PATH unless it is already set
|
||||
ELECTRON_PATH=${ELECTRON_PATH:-$EDGEHILL_PATH/electron} # Set ELECTRON_PATH unless it is already set
|
||||
|
||||
# Exit if Atom can't be found
|
||||
if [ -z "$ATOM_SHELL_PATH" ]; then
|
||||
if [ -z "$ELECTRON_PATH" ]; then
|
||||
echo "Cannot locate atom-shell. Be sure you have run script/grunt download-atom-shell first from $EDGEHILL_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We find the atom-shell executable inside of the atom-shell directory.
|
||||
$ATOM_SHELL_PATH/atom --executed-from="$(pwd)" --pid=$$ "$@" $EDGEHILL_PATH
|
||||
# We find the electron executable inside of the atom-shell directory.
|
||||
$ELECTRON_PATH/electron --executed-from="$(pwd)" --pid=$$ "$@" $EDGEHILL_PATH
|
||||
|
||||
fi
|
||||
|
||||
|
|
|
@ -75,8 +75,8 @@ module.exports = (grunt) ->
|
|||
|
||||
[major, minor, patch] = packageJson.version.split('.')
|
||||
tmpDir = os.tmpdir()
|
||||
appName = if process.platform is 'darwin' then 'Edgehill.app' else 'Edgehill'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'edgehill-build')
|
||||
appName = if process.platform is 'darwin' then 'Nylas.app' else 'Nylas'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'nylas-build')
|
||||
buildDir = path.resolve(buildDir)
|
||||
installDir = grunt.option('install-dir')
|
||||
|
||||
|
@ -89,17 +89,17 @@ module.exports = (grunt) ->
|
|||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
installDir ?= path.join(process.env.ProgramFiles, appName)
|
||||
killCommand = 'taskkill /F /IM edgehill.exe'
|
||||
killCommand = 'taskkill /F /IM nylas.exe'
|
||||
else if process.platform is 'darwin'
|
||||
contentsDir = path.join(shellAppDir, 'Contents')
|
||||
appDir = path.join(contentsDir, 'Resources', 'app')
|
||||
installDir ?= path.join('/Applications', appName)
|
||||
killCommand = 'pkill -9 Edgehill'
|
||||
killCommand = 'pkill -9 Nylas'
|
||||
else
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
|
||||
killCommand ='pkill -9 edgehill'
|
||||
killCommand ='pkill -9 nylas'
|
||||
|
||||
installDir = path.resolve(installDir)
|
||||
|
||||
|
@ -284,10 +284,10 @@ module.exports = (grunt) ->
|
|||
'create-windows-installer':
|
||||
appDirectory: shellAppDir
|
||||
outputDirectory: path.join(buildDir, 'installer')
|
||||
authors: 'Nylas'
|
||||
authors: 'Nylas Inc.'
|
||||
loadingGif: path.resolve(__dirname, '..', 'resources', 'win', 'loading.gif')
|
||||
iconUrl: 'https://raw.githubusercontent.com/atom/atom/master/resources/win/atom.ico'
|
||||
setupIcon: path.resolve(__dirname, '..', 'resources', 'win', 'edgehill.ico')
|
||||
setupIcon: path.resolve(__dirname, '..', 'resources', 'win', 'nylas.ico')
|
||||
|
||||
shell:
|
||||
'kill-atom':
|
||||
|
|
|
@ -20,33 +20,25 @@ module.exports = (grunt) ->
|
|||
rm path.join(buildDir, 'installer')
|
||||
mkdir path.dirname(buildDir)
|
||||
|
||||
# Atom-shell IS the executable. We just need to make sure our Edgehill
|
||||
# app ends up in the correct `app` folder for atom-shell to find.
|
||||
if process.platform is 'darwin'
|
||||
cp 'atom-shell/Atom.app', shellAppDir, filter: /default_app/
|
||||
cp(path.join(shellAppDir, 'Contents', 'MacOS', 'Atom'),
|
||||
path.join(shellAppDir, 'Contents', 'MacOS', 'Edgehill'))
|
||||
rm path.join(shellAppDir, 'Contents', 'MacOS', 'Atom')
|
||||
else if process.platform is 'win32'
|
||||
cp 'atom-shell', shellAppDir, filter: /default_app/
|
||||
# We can rename atom.exe to edgehill.exe, but all of the node libraries with
|
||||
# native code are hard-linked to a file called atom.exe. For now, let's just
|
||||
# leave it as atom.exe. https://github.com/atom/atom-shell/issues/713
|
||||
cp 'atom-shell/Electron.app', shellAppDir, filter: /default_app/
|
||||
cp(path.join(shellAppDir, 'Contents', 'MacOS', 'Electron'),
|
||||
path.join(shellAppDir, 'Contents', 'MacOS', 'Nylas'))
|
||||
rm path.join(shellAppDir, 'Contents', 'MacOS', 'Electron')
|
||||
else
|
||||
cp 'atom-shell', shellAppDir, filter: /default_app/
|
||||
cp path.join(shellAppDir, 'atom'), path.join(shellAppDir, 'edgehill')
|
||||
cp path.join(shellAppDir, 'atom'), path.join(shellAppDir, 'nylas')
|
||||
rm path.join(shellAppDir, 'atom')
|
||||
|
||||
mkdir appDir
|
||||
|
||||
# Note that `atom.sh` can't be renamed `edgehill.sh` because `apm`
|
||||
# is currently hard-coded to call `atom.sh`
|
||||
if process.platform isnt 'win32'
|
||||
cp 'atom.sh', path.join(appDir, 'atom.sh')
|
||||
cp 'atom.sh', path.resolve(appDir, '..', 'new-app', 'atom.sh')
|
||||
|
||||
cp 'package.json', path.join(appDir, 'package.json')
|
||||
cp path.join('resources', 'edgehill.png'), path.join(appDir, 'edgehill.png')
|
||||
cp path.join('resources', 'nylas.png'), path.join(appDir, 'nylas.png')
|
||||
|
||||
packageNames = []
|
||||
packageDirectories = []
|
||||
nonPackageDirectories = [
|
||||
'benchmark'
|
||||
|
@ -56,26 +48,19 @@ module.exports = (grunt) ->
|
|||
]
|
||||
|
||||
{devDependencies} = grunt.file.readJSON('package.json')
|
||||
for packageFolder in ['node_modules', 'internal_packages']
|
||||
for child in fs.readdirSync(packageFolder)
|
||||
directory = path.join(packageFolder, child)
|
||||
if isAtomPackage(directory)
|
||||
packageDirectories.push(directory)
|
||||
packageNames.push(child)
|
||||
else
|
||||
nonPackageDirectories.push(directory)
|
||||
|
||||
for child in fs.readdirSync('node_modules')
|
||||
directory = path.join('node_modules', child)
|
||||
if isAtomPackage(directory)
|
||||
packageDirectories.push(directory)
|
||||
else
|
||||
nonPackageDirectories.push(directory)
|
||||
|
||||
for child in fs.readdirSync('internal_packages')
|
||||
directory = path.join('internal_packages', child)
|
||||
if isAtomPackage(directory)
|
||||
packageDirectories.push(directory)
|
||||
else
|
||||
nonPackageDirectories.push(directory)
|
||||
|
||||
# Put any paths here that shouldn't end up in the built Atom.app
|
||||
# Put any paths here that shouldn't end up in the built Electron.app
|
||||
# so that it doesn't becomes larger than it needs to be.
|
||||
ignoredPaths = [
|
||||
path.join('git-utils', 'deps')
|
||||
path.join('oniguruma', 'deps')
|
||||
path.join('less', 'dist')
|
||||
path.join('npm', 'doc')
|
||||
path.join('npm', 'html')
|
||||
|
@ -101,19 +86,32 @@ module.exports = (grunt) ->
|
|||
path.join('resources', 'win')
|
||||
|
||||
# These are only require in dev mode when the grammar isn't precompiled
|
||||
path.join('atom-keymap', 'node_modules', 'loophole')
|
||||
path.join('atom-keymap', 'node_modules', 'pegjs')
|
||||
path.join('atom-keymap', 'node_modules', '.bin', 'pegjs')
|
||||
path.join('snippets', 'node_modules', 'loophole')
|
||||
path.join('snippets', 'node_modules', 'pegjs')
|
||||
path.join('snippets', 'node_modules', '.bin', 'pegjs')
|
||||
|
||||
# These aren't needed since WeakMap is built-in
|
||||
path.join('emissary', 'node_modules', 'es6-weak-map')
|
||||
path.join('property-accessors', 'node_modules', 'es6-weak-map')
|
||||
|
||||
'.DS_Store'
|
||||
'.jshintrc'
|
||||
'.npmignore'
|
||||
'.pairs'
|
||||
'.travis.yml'
|
||||
'appveyor.yml'
|
||||
'.idea'
|
||||
'.editorconfig'
|
||||
'.lint'
|
||||
'.lintignore'
|
||||
'.eslintrc'
|
||||
'.jshintignore'
|
||||
'.gitattributes'
|
||||
'.gitkeep'
|
||||
]
|
||||
|
||||
packageNames.forEach (packageName) -> ignoredPaths.push(path.join(packageName, 'spec'))
|
||||
|
||||
ignoredPaths = ignoredPaths.map (ignoredPath) -> escapeRegExp(ignoredPath)
|
||||
|
||||
# Add .* to avoid matching hunspell_dictionaries.
|
||||
|
@ -125,7 +123,6 @@ module.exports = (grunt) ->
|
|||
ignoredPaths.push "#{escapeRegExp(path.join('git-utils', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{escapeRegExp(path.join('keytar', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{escapeRegExp(path.join('nslog', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{escapeRegExp(path.join('oniguruma', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{escapeRegExp(path.join('pathwatcher', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{escapeRegExp(path.join('runas', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{escapeRegExp(path.join('scrollbar-style', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
|
@ -153,7 +150,7 @@ module.exports = (grunt) ->
|
|||
pathToCopy = path.resolve(pathToCopy)
|
||||
nodeModulesFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy)
|
||||
|
||||
packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(coffee|cjsx|jsx)$)")
|
||||
packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(cson|coffee|cjsx|jsx)$)")
|
||||
filterPackage = (pathToCopy) ->
|
||||
return true if benchmarkFolderPattern.test(pathToCopy)
|
||||
|
||||
|
@ -171,9 +168,9 @@ module.exports = (grunt) ->
|
|||
cp 'src', path.join(appDir, 'src'), filter: /.+\.(cson|coffee|cjsx|jsx)$/
|
||||
cp 'static', path.join(appDir, 'static')
|
||||
|
||||
cp path.join('apm', 'node_modules', 'atom-package-manager'), path.join(appDir, 'apm'), filter: filterNodeModule
|
||||
cp path.join('apm', 'node_modules', 'atom-package-manager'), path.resolve(appDir, '..', 'new-app', 'apm'), filter: filterNodeModule
|
||||
if process.platform isnt 'win32'
|
||||
fs.symlinkSync(path.join('..', '..', 'bin', 'apm'), path.join(appDir, 'apm', 'node_modules', '.bin', 'apm'))
|
||||
fs.symlinkSync(path.join('..', '..', 'bin', 'apm'), path.resolve(appDir, '..', 'new-app', 'apm', 'node_modules', '.bin', 'apm'))
|
||||
|
||||
if process.platform is 'darwin'
|
||||
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
|
||||
|
@ -186,9 +183,10 @@ module.exports = (grunt) ->
|
|||
cp path.join('resources', 'win', 'atom.js'), path.join(shellAppDir, 'resources', 'cli', 'atom.js')
|
||||
cp path.join('resources', 'win', 'apm.sh'), path.join(shellAppDir, 'resources', 'cli', 'apm.sh')
|
||||
|
||||
if process.platform is 'linux'
|
||||
cp path.join('resources', 'linux', 'icons'), path.join(buildDir, 'icons')
|
||||
|
||||
dependencies = ['compile', 'generate-license:save', 'generate-module-cache', 'compile-packages-slug']
|
||||
dependencies.push('copy-info-plist') if process.platform is 'darwin'
|
||||
dependencies.push('set-exe-icon') if process.platform is 'win32'
|
||||
grunt.task.run(dependencies...)
|
||||
|
||||
grunt.log.ok("Built Edgehill into #{buildDir}")
|
||||
|
|
|
@ -44,14 +44,14 @@ module.exports = (grunt) ->
|
|||
# TODO: Don't do anything now, because we need a certificate pfx file
|
||||
# issued from a certificate authority, and we don't have one.
|
||||
return callback()
|
||||
spawn {cmd: 'taskkill', args: ['/F', '/IM', 'atom.exe']}, ->
|
||||
spawn {cmd: 'taskkill', args: ['/F', '/IM', 'nylas.exe']}, ->
|
||||
cmd = process.env.JANKY_SIGNTOOL ? 'signtool'
|
||||
args = ['sign', path.join(grunt.config.get('atom.shellAppDir'), 'atom.exe')]
|
||||
args = ['sign', path.join(grunt.config.get('atom.shellAppDir'), 'nylas.exe')]
|
||||
|
||||
spawn {cmd, args}, (error) ->
|
||||
return callback(error) if error?
|
||||
|
||||
setupExePath = path.resolve(grunt.config.get('atom.buildDir'), 'installer', 'AtomSetup.exe')
|
||||
setupExePath = path.resolve(grunt.config.get('atom.buildDir'), 'installer', 'NylasSetup.exe')
|
||||
if fs.isFileSync(setupExePath)
|
||||
args = ['sign', setupExePath]
|
||||
spawn {cmd, args}, (error) -> callback(error)
|
||||
|
|
|
@ -9,5 +9,5 @@ module.exports = (grunt) ->
|
|||
helperPlistPath = path.join(contentsDir, 'Frameworks/Atom Helper.app/Contents/Info.plist')
|
||||
|
||||
# Copy custom plist files
|
||||
cp 'resources/mac/edgehill-Info.plist', plistPath
|
||||
cp 'resources/mac/nylas-Info.plist', plistPath
|
||||
cp 'resources/mac/helper-Info.plist', helperPlistPath
|
||||
|
|
|
@ -18,7 +18,7 @@ module.exports = (grunt) ->
|
|||
grunt.log.error("Failed to copy #{shellAppDir} to #{installDir}")
|
||||
|
||||
createShortcut = path.resolve 'script', 'create-shortcut.cmd'
|
||||
runas('cmd', ['/c', createShortcut, path.join(installDir, 'edgehill.exe'), 'Edgehill'])
|
||||
runas('cmd', ['/c', createShortcut, path.join(installDir, 'nylas.exe'), 'Nylas'])
|
||||
else if process.platform is 'darwin'
|
||||
rm installDir
|
||||
mkdir path.dirname(installDir)
|
||||
|
@ -29,27 +29,27 @@ module.exports = (grunt) ->
|
|||
fs.renameSync(tempFolder, installDir)
|
||||
else
|
||||
binDir = path.join(installDir, 'bin')
|
||||
shareDir = path.join(installDir, 'share', 'edgehill')
|
||||
shareDir = path.join(installDir, 'share', 'nylas')
|
||||
|
||||
iconName = path.join(shareDir,'resources', 'app', 'resources', 'edgehill.png')
|
||||
iconName = path.join(shareDir,'resources', 'app', 'resources', 'nylas.png')
|
||||
|
||||
mkdir binDir
|
||||
# Note that `atom.sh` can't be renamed `edgehill.sh` because `apm`
|
||||
# Note that `atom.sh` can't be renamed `nylas.sh` because `apm`
|
||||
# is currently hard-coded to call `atom.sh`
|
||||
cp 'atom.sh', path.join(binDir, 'edgehill')
|
||||
cp 'atom.sh', path.join(binDir, 'nylas')
|
||||
rm shareDir
|
||||
mkdir path.dirname(shareDir)
|
||||
cp shellAppDir, shareDir
|
||||
|
||||
# Create edgehill.desktop if installation not in temporary folder
|
||||
# Create nylas.desktop if installation not in temporary folder
|
||||
tmpDir = if process.env.TMPDIR? then process.env.TMPDIR else '/tmp'
|
||||
if installDir.indexOf(tmpDir) isnt 0
|
||||
desktopFile = path.join('resources', 'linux', 'edgehill.desktop.in')
|
||||
desktopInstallFile = path.join(installDir, 'share', 'applications', 'edgehill.desktop')
|
||||
desktopFile = path.join('resources', 'linux', 'nylas.desktop.in')
|
||||
desktopInstallFile = path.join(installDir, 'share', 'applications', 'nylas.desktop')
|
||||
|
||||
{description} = grunt.file.readJSON('package.json')
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'edgehill.png')
|
||||
installDir = path.join(installDir, '.') # To prevent "Exec=/usr/local//share/edgehill/edgehill"
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'nylas.png')
|
||||
installDir = path.join(installDir, '.') # To prevent "Exec=/usr/local//share/nylas/nylas"
|
||||
template = _.template(String(fs.readFileSync(desktopFile)))
|
||||
filled = template({description, installDir, iconName})
|
||||
|
||||
|
@ -58,8 +58,8 @@ module.exports = (grunt) ->
|
|||
# Create relative symbol link for apm.
|
||||
process.chdir(binDir)
|
||||
rm('apm')
|
||||
fs.symlinkSync(path.join('..', 'share', 'edgehill', 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'), 'apm')
|
||||
fs.symlinkSync(path.join('..', 'share', 'nylas', 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'), 'apm')
|
||||
|
||||
fs.chmodSync(path.join(shareDir, 'edgehill'), "755")
|
||||
fs.chmodSync(path.join(shareDir, 'nylas'), "755")
|
||||
|
||||
grunt.log.ok("Installed Edgehill into #{installDir}")
|
||||
grunt.log.ok("Installed Nylas into #{installDir}")
|
||||
|
|
|
@ -15,7 +15,7 @@ module.exports = (grunt) ->
|
|||
|
||||
getInstalledSize = (buildDir, callback) ->
|
||||
cmd = 'du'
|
||||
args = ['-sk', path.join(buildDir, 'Edgehill')]
|
||||
args = ['-sk', path.join(buildDir, 'Nylas')]
|
||||
spawn {cmd, args}, (error, {stdout}) ->
|
||||
installedSize = stdout.split(/\s+/)?[0] or '200000' # default to 200MB
|
||||
callback(null, installedSize)
|
||||
|
@ -35,12 +35,12 @@ module.exports = (grunt) ->
|
|||
section = 'devel'
|
||||
maintainer = 'Nylas <edgehill@nylas.com>'
|
||||
installDir = '/usr'
|
||||
iconName = 'edgehill'
|
||||
iconName = 'nylas'
|
||||
getInstalledSize buildDir, (error, installedSize) ->
|
||||
data = {name, version, description, section, arch, maintainer, installDir, iconName, installedSize}
|
||||
controlFilePath = fillTemplate(path.join('resources', 'linux', 'debian', 'control'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'edgehill.desktop'), data)
|
||||
icon = path.join('resources', 'edgehill.png')
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'nylas.desktop'), data)
|
||||
icon = path.join('resources', 'nylas.png')
|
||||
|
||||
cmd = path.join('script', 'mkdeb')
|
||||
args = [version, arch, controlFilePath, desktopFilePath, icon, buildDir]
|
||||
|
@ -48,5 +48,5 @@ module.exports = (grunt) ->
|
|||
if error?
|
||||
done(error)
|
||||
else
|
||||
grunt.log.ok "Created #{buildDir}/edgehill-#{version}-#{arch}.deb"
|
||||
grunt.log.ok "Created #{buildDir}/nylas-#{version}-#{arch}.deb"
|
||||
done()
|
||||
|
|
|
@ -30,12 +30,12 @@ module.exports = (grunt) ->
|
|||
|
||||
executeDmgMaker = (dmgExecutable) ->
|
||||
new Promise (resolve, reject) ->
|
||||
console.log("---> Bulding Edgehill DMG")
|
||||
console.log("---> Bulding Nylas DMG")
|
||||
spawn
|
||||
cmd: dmgExecutable
|
||||
args: [
|
||||
"--volname", "Edgehill Installer",
|
||||
"--volicon", path.join("resources", "edgehill.png"),
|
||||
"--volname", "Nylas Installer",
|
||||
"--volicon", path.join("resources", "nylas.png"),
|
||||
"--window-pos", "200", "120",
|
||||
"--window-size", "800", "400",
|
||||
"--icon-size", "100",
|
||||
|
|
|
@ -31,12 +31,12 @@ module.exports = (grunt) ->
|
|||
mkdir rpmDir
|
||||
|
||||
installDir = grunt.config.get('atom.installDir')
|
||||
shareDir = path.join(installDir, 'share', 'edgehill')
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'edgehill.png')
|
||||
shareDir = path.join(installDir, 'share', 'nylas')
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'nylas.png')
|
||||
|
||||
data = {name, version, description, installDir, iconName}
|
||||
specFilePath = fillTemplate(path.join('resources', 'linux', 'redhat', 'edgehill.spec'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'edgehill.desktop'), data)
|
||||
specFilePath = fillTemplate(path.join('resources', 'linux', 'redhat', 'nylas.spec'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'nylas.desktop'), data)
|
||||
|
||||
cmd = path.join('script', 'mkrpm')
|
||||
args = [specFilePath, desktopFilePath, buildDir]
|
||||
|
|
|
@ -62,13 +62,13 @@ getAssets = ->
|
|||
switch process.platform
|
||||
when 'darwin'
|
||||
[
|
||||
{assetName: 'edgehill-mac.zip', sourcePath: 'Edgehill.app'}
|
||||
{assetName: 'edgehill-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'}
|
||||
{assetName: 'edgehill-api.json', sourcePath: 'edgehill-api.json'}
|
||||
{assetName: 'nylas-mac.zip', sourcePath: 'Nylas.app'}
|
||||
{assetName: 'nylas-mac-symbols.zip', sourcePath: 'Nylas.breakpad.syms'}
|
||||
{assetName: 'nylas-api.json', sourcePath: 'nylas-api.json'}
|
||||
]
|
||||
when 'win32'
|
||||
assets = [{assetName: 'atom-windows.zip', sourcePath: 'Atom'}]
|
||||
for squirrelAsset in ['AtomSetup.exe', 'RELEASES', "atom-#{version}-full.nupkg"]
|
||||
assets = [{assetName: 'nylas-windows.zip', sourcePath: 'Nylas'}]
|
||||
for squirrelAsset in ['NylasSetup.exe', 'RELEASES', "nylas-#{version}-full.nupkg"]
|
||||
cp path.join(buildDir, 'installer', squirrelAsset), path.join(buildDir, squirrelAsset)
|
||||
assets.push({assetName: squirrelAsset, sourcePath: assetName})
|
||||
assets
|
||||
|
|
|
@ -117,7 +117,7 @@ For a more detailed documentation on asynchronous tests please visit the [jasmin
|
|||
|
||||
## Running specs
|
||||
|
||||
Most of the time you'll want to run specs by triggering the `window:run-package-specs` command. This command is not only to run package specs, it is also for Atom core specs. This will run all the specs in the current project's spec directory. If you want to run the Atom core specs and **all** the default package specs trigger the `window:run-all-specs` command.
|
||||
Most of the time you'll want to run specs by triggering the `application:run-package-specs` command. This command is not only to run package specs, it is also for Atom core specs. This will run all the specs in the current project's spec directory. If you want to run the Atom core specs and **all** the default package specs trigger the `window:run-all-specs` command.
|
||||
|
||||
To run a limited subset of specs use the `fdescribe` or `fit` methods. You can use those to focus a single spec or several specs. In the example above, focusing an individual spec looks like this:
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<div id="footer">
|
||||
<div class="container">
|
||||
<img src="images/edgehill.png" class="logo" />
|
||||
<img src="images/nylas.png" class="logo" />
|
||||
<div class="small">Nylas Mail Developer Preview<br><em>© 2014-2015 Nylas, Inc.</em></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<body>
|
||||
<div id="header">
|
||||
<div class="container">
|
||||
<img src="images/edgehill.png" class="logo" />
|
||||
<img src="images/nylas.png" class="logo" />
|
||||
<div class="title">Nylas Mail<div class="small">Developer Preview</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@ TitleHidden: true
|
|||
Section: Getting Started
|
||||
---
|
||||
|
||||
<img src="images/edgehill.png" class="center-logo"/>
|
||||
<img src="images/nylas.png" class="center-logo"/>
|
||||
<h2 style="text-align:center;">Nylas Package API</h2>
|
||||
<p style="text-align:center; margin:auto; margin-bottom:60px;">
|
||||
The Nylas Package API allows you to create powerful extensions to Nylas Mail. The client is built on top of Electron and runs on Mac OS X, Windows, and Linux. It exposes rich APIs for working with the mail, contacts, and calendar and a robust local cache layer. Your packages can leverage NodeJS and other web technologies to create innovative new experiences.
|
||||
|
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
|
@ -10,7 +10,6 @@ DeveloperBarStore = Reflux.createStore
|
|||
@_setStoreDefaults()
|
||||
@_registerListeners()
|
||||
|
||||
|
||||
########### PUBLIC #####################################################
|
||||
|
||||
curlHistory: -> @_curlHistory
|
||||
|
@ -39,6 +38,7 @@ DeveloperBarStore = Reflux.createStore
|
|||
@listenTo Actions.longPollStateChanged, @_onLongPollStateChange
|
||||
@listenTo Actions.clearDeveloperConsole, @_onClear
|
||||
@listenTo Actions.showDeveloperConsole, @_onShow
|
||||
@listenTo Actions.sendFeedback, @_onSendFeedback
|
||||
|
||||
_onShow: ->
|
||||
@_visible = true
|
||||
|
@ -86,4 +86,58 @@ DeveloperBarStore = Reflux.createStore
|
|||
|
||||
@triggerThrottled(@)
|
||||
|
||||
<<<<<<< HEAD:internal_packages/inbox-activity-bar/lib/activity-bar-store.coffee
|
||||
_onSendFeedback: ->
|
||||
{NamespaceStore,
|
||||
Contact,
|
||||
Message,
|
||||
DatabaseStore} = require 'nylas-exports'
|
||||
|
||||
user = NamespaceStore.current().name
|
||||
|
||||
debugData = JSON.stringify({
|
||||
queries: @_curlHistory
|
||||
}, null, '\t')
|
||||
|
||||
# Remove API tokens from URLs included in the debug data
|
||||
# This regex detects ://user:pass@ and removes it.
|
||||
debugData = debugData.replace(/:\/\/(\w)*:(\w)?@/g, '://')
|
||||
|
||||
draft = new Message
|
||||
from: [NamespaceStore.current().me()]
|
||||
to: [
|
||||
new Contact
|
||||
name: "Nylas Team"
|
||||
email: "feedback@nylas.com"
|
||||
]
|
||||
date: (new Date)
|
||||
draft: true
|
||||
subject: "Feedback"
|
||||
namespaceId: NamespaceStore.current().id
|
||||
body: """
|
||||
Hi, Nylas team! I have some feedback for you.<br/>
|
||||
<br/>
|
||||
<b>What happened:</b><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<b>Impact:</b><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<b>Feedback:</b><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<b>Environment:</b><br/>
|
||||
I'm using Edgehill #{atom.getVersion()} and my platform is #{process.platform}-#{process.arch}.<br/>
|
||||
--<br/>
|
||||
#{user}<br/>
|
||||
-- Extra Debugging Data --<br/>
|
||||
#{debugData}
|
||||
"""
|
||||
DatabaseStore.persistModel(draft).then ->
|
||||
DatabaseStore.localIdForModel(draft).then (localId) ->
|
||||
Actions.composePopoutDraft(localId)
|
||||
|
||||
module.exports = ActivityBarStore
|
||||
=======
|
||||
module.exports = DeveloperBarStore
|
||||
>>>>>>> master:internal_packages/developer-bar/lib/developer-bar-store.coffee
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
_ = require 'underscore'
|
||||
ipc = require 'ipc'
|
||||
React = require 'react/addons'
|
||||
{DatabaseStore,
|
||||
NamespaceStore,
|
||||
|
@ -28,7 +27,6 @@ class DeveloperBar extends React.Component
|
|||
filter: ''
|
||||
|
||||
componentDidMount: =>
|
||||
ipc.on 'report-issue', => @_onFeedback()
|
||||
@taskQueueUnsubscribe = TaskQueue.listen @_onChange
|
||||
@activityStoreUnsubscribe = DeveloperBarStore.listen @_onChange
|
||||
|
||||
|
@ -62,7 +60,7 @@ class DeveloperBar extends React.Component
|
|||
</div>
|
||||
</div>
|
||||
<div className="btn-container pull-right">
|
||||
<div className="btn" onClick={@_onFeedback}>Feedback</div>
|
||||
<div className="btn" onClick={Actions.sendFeedback}>Feedback</div>
|
||||
</div>
|
||||
<div className="btn-container pull-right">
|
||||
<div className="btn" onClick={@_onToggleRegions}>Component Regions</div>
|
||||
|
@ -152,53 +150,6 @@ class DeveloperBar extends React.Component
|
|||
_onToggleRegions: =>
|
||||
Actions.toggleComponentRegions()
|
||||
|
||||
_onFeedback: =>
|
||||
user = NamespaceStore.current().name
|
||||
|
||||
debugData = JSON.stringify({
|
||||
queries: @state.curlHistory,
|
||||
queue: @state.queue,
|
||||
completed: @state.completed
|
||||
}, null, '\t')
|
||||
|
||||
# Remove API tokens from URLs included in the debug data
|
||||
# This regex detects ://user:pass@ and removes it.
|
||||
debugData = debugData.replace(/:\/\/(\w)*:(\w)?@/g, '://')
|
||||
|
||||
draft = new Message
|
||||
from: [NamespaceStore.current().me()]
|
||||
to: [
|
||||
new Contact
|
||||
name: "Nylas Team"
|
||||
email: "feedback@nylas.com"
|
||||
]
|
||||
date: (new Date)
|
||||
draft: true
|
||||
subject: "Feedback"
|
||||
namespaceId: NamespaceStore.current().id
|
||||
body: """
|
||||
Hi, Nylas team! I have some feedback for you.<br/>
|
||||
<br/>
|
||||
<b>What happened:</b><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<b>Impact:</b><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<b>Feedback:</b><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<b>Environment:</b><br/>
|
||||
I'm using Edgehill #{atom.getVersion()} and my platform is #{process.platform}-#{process.arch}.<br/>
|
||||
--<br/>
|
||||
#{user}<br/>
|
||||
-- Extra Debugging Data --<br/>
|
||||
#{debugData}
|
||||
"""
|
||||
DatabaseStore.persistModel(draft).then ->
|
||||
DatabaseStore.localIdForModel(draft).then (localId) ->
|
||||
Actions.composePopoutDraft(localId)
|
||||
|
||||
_getStateFromStores: =>
|
||||
visible: DeveloperBarStore.visible()
|
||||
queue: TaskQueue._queue
|
||||
|
|
|
@ -31,6 +31,9 @@ class ContainerView extends React.Component
|
|||
if webview
|
||||
node = React.findDOMNode(webview)
|
||||
if node.hasListeners is undefined
|
||||
# Remove as soon as possible. Initial src is not correctly loaded
|
||||
# on webview, and this fixes it. Electron 0.26.0
|
||||
setTimeout -> node.src = node.src
|
||||
node.addEventListener 'new-window', (e) ->
|
||||
require('shell').openExternal(e.url)
|
||||
node.addEventListener 'did-start-loading', (e) ->
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
'alt-cmd-i': 'window:toggle-dev-tools'
|
||||
'cmd-ctrl-f': 'window:toggle-full-screen'
|
||||
'ctrl-alt-cmd-l': 'window:reload'
|
||||
'cmd-alt-ctrl-p': 'window:run-package-specs'
|
||||
'cmd-alt-ctrl-p': 'application:run-package-specs'
|
||||
|
||||
'body div *[contenteditable]':
|
||||
'cmd-z': 'core:undo'
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
# Linux application keys
|
||||
'ctrl-q': 'application:quit'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
|
||||
# Linux core keys
|
||||
'ctrl-z': 'core:undo'
|
||||
|
@ -30,10 +29,11 @@
|
|||
'ctrl--': 'window:decrease-font-size'
|
||||
'ctrl-_': 'window:decrease-font-size'
|
||||
'ctrl-0': 'window:reset-font-size'
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
'ctrl-alt-r': 'window:reload'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-shift-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'application:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
'body div *[contenteditable]':
|
||||
'ctrl-z': 'core:undo'
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
'ctrl--': 'window:decrease-font-size'
|
||||
'ctrl-_': 'window:decrease-font-size'
|
||||
'ctrl-0': 'window:reset-font-size'
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
'ctrl-alt-r': 'window:reload'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'application:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
'body div *[contenteditable]':
|
||||
'ctrl-z': 'core:undo'
|
||||
|
|
|
@ -49,7 +49,16 @@
|
|||
{ label: 'Toggle Full Screen', command: 'window:toggle-full-screen' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ label: 'Open In Dev Mode...', command: 'application:open-dev' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Run Nylas Mail Specs', command: 'application:run-all-specs' }
|
||||
{ label: 'Run Package Specs', command: 'application:run-package-specs' }
|
||||
{ label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Window'
|
||||
submenu: [
|
||||
|
@ -65,7 +74,7 @@
|
|||
{
|
||||
label: 'Help'
|
||||
submenu: [
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Send Feedback to Nylas', command: 'application:send-feedback' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -32,13 +32,22 @@
|
|||
{ label: 'Toggle Menu Bar', command: 'window:toggle-menu-bar' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ label: 'Open In &Dev Mode...', command: 'application:open-dev' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Run &Nylas Mail Specs', command: 'application:run-all-specs' }
|
||||
{ label: 'Run Package &Specs', command: 'application:run-package-specs' }
|
||||
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Send Feedback to Nylas', command: 'application:send-feedback' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -34,7 +34,16 @@
|
|||
{ label: 'Toggle Menu Bar', command: 'window:toggle-menu-bar' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ label: 'Open In &Dev Mode...', command: 'application:open-dev' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Run &Atom Specs', command: 'application:run-all-specs' }
|
||||
{ label: 'Run Package &Specs', command: 'application:run-package-specs' }
|
||||
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
|
@ -43,7 +52,7 @@
|
|||
{ label: 'Check for Update', command: 'application:check-for-update', visible: false}
|
||||
{ label: 'Downloading Update', enabled: false, visible: false}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Send Feedback to Nylas', command: 'application:send-feedback' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -11,8 +11,9 @@
|
|||
"bugs": {
|
||||
"url": "https://github.com/nylas/edgehill/issues"
|
||||
},
|
||||
"atomShellVersion": "0.21.0",
|
||||
"atomShellVersion": "0.26.0",
|
||||
"dependencies": {
|
||||
"asar": "^0.5.0",
|
||||
"6to5-core": "^3.5",
|
||||
"async": "^0.9",
|
||||
"atom-keymap": "^3.1",
|
||||
|
@ -43,9 +44,8 @@
|
|||
"moment": "^2.8",
|
||||
"moment-timezone": "^0.3",
|
||||
"nslog": "^2.0.0",
|
||||
"oniguruma": "^4.0.0",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^4.0",
|
||||
"pathwatcher": "^4.4.0",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"raven": "0.7.2",
|
||||
|
@ -73,7 +73,8 @@
|
|||
"underscore": "^1.8",
|
||||
"underscore.string": "^3.0",
|
||||
"vm-compatibility-layer": "0.1.0",
|
||||
"spellchecker": "2.2.0"
|
||||
"spellchecker": "2.2.0",
|
||||
"aws-sdk": "2.1.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"proxyquire": "git+https://github.com/bengotow/proxyquire",
|
||||
|
|
|
@ -8,4 +8,4 @@ Architecture: <%= arch %>
|
|||
Installed-Size: <%= installedSize %>
|
||||
Maintainer: <%= maintainer %>
|
||||
Description: <%= description %>
|
||||
Edgehill is an email OS
|
||||
Nylas is an email OS
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
Name: <%= name %>
|
||||
Version: <%= version %>
|
||||
Release: 0.1%{?dist}
|
||||
Summary: Edgehill is an Email OS
|
||||
License: Proprietary
|
||||
URL: https://nylas.com/
|
||||
AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
|
||||
|
||||
%description
|
||||
<%= description %>
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/local/share/edgehill
|
||||
cp -r /tmp/edgehill-build/Edgehill/* %{buildroot}/usr/local/share/edgehill
|
||||
mkdir -p %{buildroot}/usr/local/bin/
|
||||
ln -sf /usr/local/share/edgehill/resources/app/apm/node_modules/.bin/apm %{buildroot}/usr/local/bin/apm
|
||||
cp atom.sh %{buildroot}/usr/local/bin/edgehill
|
||||
chmod 755 edgehill
|
||||
mkdir -p %{buildroot}/usr/local/share/applications/
|
||||
mv edgehill.desktop %{buildroot}/usr/local/share/applications/
|
||||
|
||||
%files
|
||||
/usr/local/bin/edgehill
|
||||
/usr/local/bin/apm
|
||||
/usr/local/share/edgehill/
|
||||
/usr/local/share/applications/edgehill.desktop
|
26
resources/linux/redhat/nylas.spec.in
Normal file
26
resources/linux/redhat/nylas.spec.in
Normal file
|
@ -0,0 +1,26 @@
|
|||
Name: <%= name %>
|
||||
Version: <%= version %>
|
||||
Release: 0.1%{?dist}
|
||||
Summary: Nylas is an Email OS
|
||||
License: Proprietary
|
||||
URL: https://nylas.com/
|
||||
AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
|
||||
|
||||
%description
|
||||
<%= description %>
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/local/share/Nylas
|
||||
cp -r /tmp/nylas-build/Nylas/* %{buildroot}/usr/local/share/Nylas
|
||||
mkdir -p %{buildroot}/usr/local/bin/
|
||||
ln -sf /usr/local/share/nylas/resources/app/apm/node_modules/.bin/apm %{buildroot}/usr/local/bin/apm
|
||||
cp atom.sh %{buildroot}/usr/local/bin/nylas
|
||||
chmod 755 nylas
|
||||
mkdir -p %{buildroot}/usr/local/share/applications/
|
||||
mv nylas.desktop %{buildroot}/usr/local/share/applications/
|
||||
|
||||
%files
|
||||
/usr/local/bin/nylas
|
||||
/usr/local/bin/apm
|
||||
/usr/local/share/nylas/
|
||||
/usr/local/share/applications/nylas.desktop
|
|
@ -3,9 +3,9 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Edgehill</string>
|
||||
<string>Nylas</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>edgehill.icns</string>
|
||||
<string>nylas.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.nylas.nylas-mail</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<string>edgehill</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Edgehill Shared Session Protocol</string>
|
||||
<string>Nylas Shared Session Protocol</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
@ -47,7 +47,7 @@ function bootstrap() {
|
|||
|
||||
var gruntPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'grunt');
|
||||
|
||||
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season', 'grim'];
|
||||
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'roaster', 'season', 'grim'];
|
||||
|
||||
var buildInstallCommand = initialNpmCommand + npmFlags + 'install';
|
||||
var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')};
|
||||
|
|
|
@ -11,7 +11,7 @@ process.chdir(path.dirname(__dirname));
|
|||
var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
|
||||
var tmpdir = os.tmpdir();
|
||||
|
||||
// Windows: Use START as a way to ignore error if Edgehill.exe isnt running
|
||||
// Windows: Use START as a way to ignore error if nylas.exe isnt running
|
||||
var killatom = process.platform === 'win32' ? 'START taskkill /F /IM ' + productName + '.exe' : 'pkill -9 ' + productName + ' || true';
|
||||
|
||||
var commands = [
|
||||
|
|
12
script/mkdeb
12
script/mkdeb
|
@ -17,7 +17,7 @@ FILE_MODE=755
|
|||
|
||||
TARGET_ROOT="`mktemp -d`"
|
||||
chmod $FILE_MODE "$TARGET_ROOT"
|
||||
TARGET="$TARGET_ROOT/edgehill-$VERSION-$ARCH"
|
||||
TARGET="$TARGET_ROOT/nylas-$VERSION-$ARCH"
|
||||
|
||||
mkdir -m $FILE_MODE -p "$TARGET/usr"
|
||||
env INSTALL_PREFIX="$TARGET/usr" script/grunt install
|
||||
|
@ -31,17 +31,17 @@ cp "$DESKTOP_FILE" "$TARGET/usr/share/applications"
|
|||
mkdir -m $FILE_MODE -p "$TARGET/usr/share/pixmaps"
|
||||
cp "$ICON_FILE" "$TARGET/usr/share/pixmaps"
|
||||
|
||||
# Copy generated LICENSE.md to /usr/share/doc/edgehill/copyright
|
||||
mkdir -m $FILE_MODE -p "$TARGET/usr/share/doc/edgehill"
|
||||
cp "$TARGET/usr/share/edgehill/resources/app/LICENSE.md" "$TARGET/usr/share/doc/edgehill/copyright"
|
||||
# Copy generated LICENSE.md to /usr/share/doc/nylas/copyright
|
||||
mkdir -m $FILE_MODE -p "$TARGET/usr/share/doc/nylas"
|
||||
cp "$TARGET/usr/share/nylas/resources/app/LICENSE.md" "$TARGET/usr/share/doc/nylas/copyright"
|
||||
|
||||
# Add lintian overrides
|
||||
mkdir -m $FILE_MODE -p "$TARGET/usr/share/lintian/overrides"
|
||||
cp "$ROOT/resources/linux/debian/lintian-overrides" "$TARGET/usr/share/lintian/overrides/edgehill"
|
||||
cp "$ROOT/resources/linux/debian/lintian-overrides" "$TARGET/usr/share/lintian/overrides/nylas"
|
||||
|
||||
# Remove executable bit from .node files
|
||||
find "$TARGET" -type f -name "*.node" -exec chmod a-x {} \;
|
||||
|
||||
fakeroot dpkg-deb -b "$TARGET"
|
||||
mv "$TARGET_ROOT/edgehill-$VERSION-$ARCH.deb" "$DEB_PATH"
|
||||
mv "$TARGET_ROOT/nylas-$VERSION-$ARCH.deb" "$DEB_PATH"
|
||||
rm -rf "$TARGET_ROOT"
|
||||
|
|
|
@ -11,13 +11,13 @@ ARCH=`uname -m`
|
|||
|
||||
rpmdev-setuptree
|
||||
|
||||
cp -r $BUILD_DIRECTORY/Edgehill/* $RPM_BUILD_ROOT/BUILD
|
||||
cp -r $BUILD_DIRECTORY/Nylas/* $RPM_BUILD_ROOT/BUILD
|
||||
cp $SPEC_FILE $RPM_BUILD_ROOT/SPECS
|
||||
cp ./atom.sh $RPM_BUILD_ROOT/BUILD
|
||||
cp $RPM_BUILD_ROOT/BUILD/atom.sh $RPM_BUILD_ROOT/BUILD/edgehill
|
||||
cp $RPM_BUILD_ROOT/BUILD/atom.sh $RPM_BUILD_ROOT/BUILD/nylas
|
||||
cp $DESKTOP_FILE $RPM_BUILD_ROOT/BUILD
|
||||
|
||||
rpmbuild -ba $SPEC_FILE
|
||||
cp $RPM_BUILD_ROOT/RPMS/$ARCH/edgehill-*.rpm $BUILD_DIRECTORY/rpm
|
||||
cp $RPM_BUILD_ROOT/RPMS/$ARCH/nylas-*.rpm $BUILD_DIRECTORY/rpm
|
||||
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
|
|
@ -4,8 +4,8 @@ set -e
|
|||
|
||||
BUILT_PRODUCTS_DIR=$1
|
||||
VERSION=$2
|
||||
PLIST_PATH="$BUILT_PRODUCTS_DIR/Edgehill.app/Contents/Info.plist"
|
||||
HELPER_PLIST_PATH="$BUILT_PRODUCTS_DIR/Edgehill.app/Contents/Frameworks/Atom Helper.app/Contents/Info.plist"
|
||||
PLIST_PATH="$BUILT_PRODUCTS_DIR/Nylas.app/Contents/Info.plist"
|
||||
HELPER_PLIST_PATH="$BUILT_PRODUCTS_DIR/Nylas.app/Contents/Frameworks/Atom Helper.app/Contents/Info.plist"
|
||||
|
||||
# Update version
|
||||
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $VERSION" "$PLIST_PATH"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Reflux = require 'reflux'
|
||||
Actions = require '../src/flux/actions'
|
||||
ActionBridge = require '../src/flux/action-bridge'
|
||||
Message = require '../src/flux/models/message'
|
||||
DatabaseStore = require '../src/flux/stores/database-store'
|
||||
NamespaceStore = require '../src/flux/stores/namespace-store'
|
||||
ActionBridge = require '../src/flux/action-bridge',
|
||||
_ = require 'underscore'
|
||||
|
||||
ipc =
|
||||
|
@ -86,17 +86,16 @@ describe "ActionBridge", ->
|
|||
Actions.didSwapModel.firing = false
|
||||
@bridge.onRebroadcast(ActionBridge.TargetWindows.ALL, 'didSwapModel', [{oldModel: '1', newModel: 2}])
|
||||
expect(ipc.send).toHaveBeenCalledWith('action-bridge-rebroadcast-to-all', 'popout', 'didSwapModel', '[{"oldModel":"1","newModel":2}]')
|
||||
|
||||
|
||||
describe "when called with TargetWindows.MAIN", ->
|
||||
it "should broadcast the action over IPC to the main window only", ->
|
||||
spyOn(ipc, 'send')
|
||||
Actions.didSwapModel.firing = false
|
||||
@bridge.onRebroadcast(ActionBridge.TargetWindows.MAIN, 'didSwapModel', [{oldModel: '1', newModel: 2}])
|
||||
expect(ipc.send).toHaveBeenCalledWith('action-bridge-rebroadcast-to-main', 'popout', 'didSwapModel', '[{"oldModel":"1","newModel":2}]')
|
||||
|
||||
|
||||
it "should not do anything if the current invocation of the Action was triggered by itself", ->
|
||||
spyOn(ipc, 'send')
|
||||
Actions.didSwapModel.firing = true
|
||||
@bridge.onRebroadcast(ActionBridge.TargetWindows.ALL, 'didSwapModel', [{oldModel: '1', newModel: 2}])
|
||||
expect(ipc.send).not.toHaveBeenCalled()
|
||||
|
||||
|
|
|
@ -206,8 +206,8 @@ class AtomReporter extends View
|
|||
specComplete: (spec) ->
|
||||
specSummaryElement = $("#spec-summary-#{spec.id}")
|
||||
specSummaryElement.removeClass('pending')
|
||||
specSummaryElement.setTooltip(title: spec.getFullName(), container: '.spec-reporter')
|
||||
|
||||
specSummaryElement.attr('title', spec.getFullName())
|
||||
|
||||
results = spec.results()
|
||||
if results.skipped
|
||||
specSummaryElement.addClass("skipped")
|
||||
|
|
|
@ -201,10 +201,12 @@ class Atom extends Model
|
|||
if event.binding.command.indexOf('application:') is 0 and event.binding.selector is "body"
|
||||
ipc.send('command', event.binding.command)
|
||||
|
||||
unless @inSpecMode()
|
||||
@actionBridge = new ActionBridge(ipc)
|
||||
|
||||
@commands = new CommandRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@styles = new StyleManager
|
||||
@actionBridge = new ActionBridge(ipc)
|
||||
document.head.appendChild(new StylesElement)
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode})
|
||||
@menu = new MenuManager({resourcePath})
|
||||
|
|
|
@ -5,6 +5,7 @@ NylasProtocolHandler = require './nylas-protocol-handler'
|
|||
AutoUpdateManager = require './auto-update-manager'
|
||||
WindowManager = require './window-manager'
|
||||
Config = require '../config'
|
||||
dialog = require 'dialog'
|
||||
|
||||
fs = require 'fs-plus'
|
||||
Menu = require 'menu'
|
||||
|
@ -25,6 +26,8 @@ socketPath =
|
|||
else
|
||||
path.join(os.tmpdir(), 'edgehill.sock')
|
||||
|
||||
configDirPath = fs.absolute('~/.nylas')
|
||||
|
||||
# The application's singleton class.
|
||||
#
|
||||
# It's the entry point into the Atom application and maintains the global state
|
||||
|
@ -34,7 +37,7 @@ module.exports =
|
|||
class Application
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
|
||||
# Public: The entry point into the Atom application.
|
||||
# Public: The entry point into the Nylas Mail application.
|
||||
@open: (options) ->
|
||||
createApplication = -> new Application(options)
|
||||
|
||||
|
@ -69,8 +72,7 @@ class Application
|
|||
|
||||
global.application = this
|
||||
|
||||
configDirPath = fs.absolute('~/.nylas')
|
||||
@config = new Config({configDirPath})
|
||||
@config = new Config({configDirPath, @resourcePath})
|
||||
@config.load()
|
||||
|
||||
@databases = {}
|
||||
|
@ -187,8 +189,27 @@ class Application
|
|||
# needs to manually bubble them up to the Application instance via IPC or they won't be
|
||||
# handled. This happens in workspace-element.coffee
|
||||
handleEvents: ->
|
||||
@on 'application:run-all-specs', -> @runSpecs(exitWhenDone: false, resourcePath: global.devResourcePath, safeMode: @windowManager.focusedWindow()?.safeMode)
|
||||
@on 'application:run-benchmarks', -> @runBenchmarks()
|
||||
@on 'application:run-all-specs', ->
|
||||
@runSpecs
|
||||
exitWhenDone: false
|
||||
resourcePath: global.devResourcePath
|
||||
safeMode: @windowManager.focusedWindow()?.safeMode
|
||||
|
||||
@on 'application:run-package-specs', ->
|
||||
dialog.showOpenDialog {
|
||||
title: 'Choose a Package Directory'
|
||||
defaultPath: configDirPath,
|
||||
properties: ['openDirectory']
|
||||
}, (filenames) =>
|
||||
return if filenames.length is 0
|
||||
@runSpecs
|
||||
exitWhenDone: false
|
||||
resourcePath: global.devResourcePath
|
||||
specDirectory: filenames[0]
|
||||
|
||||
@on 'application:run-benchmarks', ->
|
||||
@runBenchmarks()
|
||||
|
||||
@on 'application:logout', =>
|
||||
for path, val of @databases
|
||||
@teardownDatabase(path)
|
||||
|
@ -202,18 +223,17 @@ class Application
|
|||
atomWindow ?= @windowManager.focusedWindow()
|
||||
atomWindow?.browserWindow.inspectElement(x, y)
|
||||
|
||||
@on 'application:open-documentation', -> require('shell').openExternal('https://atom.io/docs/latest/?app')
|
||||
@on 'application:open-discussions', -> require('shell').openExternal('https://discuss.atom.io')
|
||||
@on 'application:open-roadmap', -> require('shell').openExternal('https://atom.io/roadmap?app')
|
||||
@on 'application:open-faq', -> require('shell').openExternal('https://atom.io/faq')
|
||||
@on 'application:open-terms-of-use', -> require('shell').openExternal('https://atom.io/terms')
|
||||
@on 'application:report-issue', => @_reportIssue()
|
||||
@on 'application:search-issues', -> require('shell').openExternal('https://github.com/issues?q=+is%3Aissue+user%3Aatom')
|
||||
@on 'application:send-feedback', => @windowManager.sendToMainWindow('send-feedback')
|
||||
@on 'application:show-main-window', => @windowManager.ensurePrimaryWindowOnscreen()
|
||||
@on 'application:check-for-update', => @autoUpdateManager.check()
|
||||
@on 'application:install-update', =>
|
||||
@quitting = true
|
||||
@autoUpdateManager.install()
|
||||
@on 'application:open-dev', =>
|
||||
@devMode = true
|
||||
@windowManager.closeMainWindow()
|
||||
@windowManager.devMode = true
|
||||
@windowManager.ensurePrimaryWindowOnscreen()
|
||||
|
||||
if process.platform is 'darwin'
|
||||
@on 'application:about', -> Menu.sendActionToFirstResponder('orderFrontStandardAboutPanel:')
|
||||
|
@ -257,9 +277,6 @@ class Application
|
|||
win = BrowserWindow.fromWebContents(event.sender)
|
||||
@applicationMenu.update(win, template, keystrokesByCommand)
|
||||
|
||||
ipc.on 'run-package-specs', (event, specDirectory) =>
|
||||
@runSpecs({resourcePath: global.devResourcePath, specDirectory: specDirectory, exitWhenDone: false})
|
||||
|
||||
ipc.on 'command', (event, command) =>
|
||||
@emit(command)
|
||||
|
||||
|
@ -380,6 +397,3 @@ class Application
|
|||
isSpec = true
|
||||
devMode = true
|
||||
new AtomWindow({bootstrapScript, @resourcePath, exitWhenDone, isSpec, specDirectory, devMode})
|
||||
|
||||
_reportIssue: ->
|
||||
@windowManager.sendToMainWindow('report-issue')
|
||||
|
|
|
@ -10,7 +10,7 @@ module.exports =
|
|||
class AtomWindow
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
|
||||
@iconPath: path.resolve(__dirname, '..', '..', 'resources', 'edgehill.png')
|
||||
@iconPath: path.resolve(__dirname, '..', '..', 'resources', 'nylas.png')
|
||||
@includeShellLoadTime: true
|
||||
|
||||
browserWindow: null
|
||||
|
@ -40,6 +40,8 @@ class AtomWindow
|
|||
show: false
|
||||
title: title ? 'Nylas'
|
||||
frame: frame ? true
|
||||
#https://atomio.slack.com/archives/electron/p1432056952000608
|
||||
'standard-window': frame ? true
|
||||
width: width
|
||||
height: height
|
||||
resizable: resizable ? true
|
||||
|
|
|
@ -33,6 +33,10 @@ class AutoUpdateManager
|
|||
else
|
||||
autoUpdater = require 'auto-updater'
|
||||
|
||||
autoUpdater.on 'error', (event, message) =>
|
||||
@setState(ErrorState)
|
||||
console.error "Error Downloading Update: #{message}"
|
||||
|
||||
autoUpdater.setFeedUrl @feedUrl
|
||||
|
||||
autoUpdater.on 'checking-for-update', =>
|
||||
|
@ -44,10 +48,6 @@ class AutoUpdateManager
|
|||
autoUpdater.on 'update-available', =>
|
||||
@setState(DownladingState)
|
||||
|
||||
autoUpdater.on 'error', (event, message) =>
|
||||
@setState(ErrorState)
|
||||
console.error "Error Downloading Update: #{message}"
|
||||
|
||||
autoUpdater.on 'update-downloaded', (event, @releaseNotes, @releaseVersion) =>
|
||||
@setState(UpdateAvailableState)
|
||||
@emitUpdateAvailableEvent(@getWindows()...)
|
||||
|
@ -84,7 +84,7 @@ class AutoUpdateManager
|
|||
autoUpdater.quitAndInstall()
|
||||
|
||||
iconURL: ->
|
||||
url = path.join(process.resourcesPath, 'app', 'edgehill.png')
|
||||
url = path.join(process.resourcesPath, 'app', 'nylas.png')
|
||||
return undefined unless fs.existsSync(url)
|
||||
url
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
global.shellStartTime = Date.now()
|
||||
|
||||
errorReporter = new (require '../error-reporter')
|
||||
|
||||
app = require 'app'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
|
|
|
@ -6,14 +6,11 @@ path = require 'path'
|
|||
#
|
||||
# This is necessary on Windows since it doesn't support shebang `#!` lines.
|
||||
#
|
||||
# Section: Atom
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ```coffee
|
||||
# {BufferedNodeProcess} = require 'atom'
|
||||
# ```
|
||||
#
|
||||
module.exports =
|
||||
class BufferedNodeProcess extends BufferedProcess
|
||||
|
||||
|
@ -51,5 +48,8 @@ class BufferedNodeProcess extends BufferedProcess
|
|||
options.env ?= Object.create(process.env)
|
||||
options.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = 1
|
||||
|
||||
args = args?.slice() ? []
|
||||
args.unshift(command)
|
||||
args.unshift('--no-deprecation')
|
||||
|
||||
super({command: node, args, options, stdout, stderr, exit})
|
||||
|
|
|
@ -6,8 +6,6 @@ path = require 'path'
|
|||
# Extended: A wrapper which provides standard error/output line buffering for
|
||||
# Node's ChildProcess.
|
||||
#
|
||||
# Section: Atom
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ```coffee
|
||||
|
@ -19,7 +17,6 @@ path = require 'path'
|
|||
# exit = (code) -> console.log("ps -ef exited with #{code}")
|
||||
# process = new BufferedProcess({command, args, stdout, exit})
|
||||
# ```
|
||||
#
|
||||
module.exports =
|
||||
class BufferedProcess
|
||||
###
|
||||
|
@ -51,6 +48,7 @@ class BufferedProcess
|
|||
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
|
||||
@emitter = new Emitter
|
||||
options ?= {}
|
||||
@command = command
|
||||
# Related to joyent/node#2318
|
||||
if process.platform is 'win32'
|
||||
# Quote all arguments and escapes inner quotes
|
||||
|
@ -72,50 +70,12 @@ class BufferedProcess
|
|||
cmdArgs = ['/s', '/c', "\"#{cmdArgs.join(' ')}\""]
|
||||
cmdOptions = _.clone(options)
|
||||
cmdOptions.windowsVerbatimArguments = true
|
||||
@process = ChildProcess.spawn(@getCmdPath(), cmdArgs, cmdOptions)
|
||||
@spawn(@getCmdPath(), cmdArgs, cmdOptions)
|
||||
else
|
||||
@process = ChildProcess.spawn(command, args, options)
|
||||
@spawn(command, args, options)
|
||||
|
||||
@killed = false
|
||||
|
||||
stdoutClosed = true
|
||||
stderrClosed = true
|
||||
processExited = true
|
||||
exitCode = 0
|
||||
triggerExitCallback = ->
|
||||
return if @killed
|
||||
if stdoutClosed and stderrClosed and processExited
|
||||
exit?(exitCode)
|
||||
|
||||
if stdout
|
||||
stdoutClosed = false
|
||||
@bufferStream @process.stdout, stdout, ->
|
||||
stdoutClosed = true
|
||||
triggerExitCallback()
|
||||
|
||||
if stderr
|
||||
stderrClosed = false
|
||||
@bufferStream @process.stderr, stderr, ->
|
||||
stderrClosed = true
|
||||
triggerExitCallback()
|
||||
|
||||
if exit
|
||||
processExited = false
|
||||
@process.on 'exit', (code) ->
|
||||
exitCode = code
|
||||
processExited = true
|
||||
triggerExitCallback()
|
||||
|
||||
@process.on 'error', (error) =>
|
||||
handled = false
|
||||
handle = -> handled = true
|
||||
|
||||
@emitter.emit 'will-throw-error', {error, handle}
|
||||
|
||||
if error.code is 'ENOENT' and error.syscall.indexOf('spawn') is 0
|
||||
error = new Error("Failed to spawn command `#{command}`. Make sure `#{command}` is installed and on your PATH", error.path)
|
||||
error.name = 'BufferedProcessError'
|
||||
|
||||
throw error unless handled
|
||||
@handleEvents(stdout, stderr, exit)
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
|
@ -167,6 +127,8 @@ class BufferedProcess
|
|||
# This is required since killing the cmd.exe does not terminate child
|
||||
# processes.
|
||||
killOnWindows: ->
|
||||
return unless @process?
|
||||
|
||||
parentPid = @process.pid
|
||||
cmd = 'wmic'
|
||||
args = [
|
||||
|
@ -177,7 +139,12 @@ class BufferedProcess
|
|||
'processid'
|
||||
]
|
||||
|
||||
wmicProcess = ChildProcess.spawn(cmd, args)
|
||||
try
|
||||
wmicProcess = ChildProcess.spawn(cmd, args)
|
||||
catch spawnError
|
||||
@killProcess()
|
||||
return
|
||||
|
||||
wmicProcess.on 'error', -> # ignore errors
|
||||
output = ''
|
||||
wmicProcess.stdout.on 'data', (data) -> output += data
|
||||
|
@ -223,3 +190,55 @@ class BufferedProcess
|
|||
@killProcess()
|
||||
|
||||
undefined
|
||||
|
||||
spawn: (command, args, options) ->
|
||||
try
|
||||
@process = ChildProcess.spawn(command, args, options)
|
||||
catch spawnError
|
||||
process.nextTick => @handleError(spawnError)
|
||||
|
||||
handleEvents: (stdout, stderr, exit) ->
|
||||
return unless @process?
|
||||
|
||||
stdoutClosed = true
|
||||
stderrClosed = true
|
||||
processExited = true
|
||||
exitCode = 0
|
||||
triggerExitCallback = ->
|
||||
return if @killed
|
||||
if stdoutClosed and stderrClosed and processExited
|
||||
exit?(exitCode)
|
||||
|
||||
if stdout
|
||||
stdoutClosed = false
|
||||
@bufferStream @process.stdout, stdout, ->
|
||||
stdoutClosed = true
|
||||
triggerExitCallback()
|
||||
|
||||
if stderr
|
||||
stderrClosed = false
|
||||
@bufferStream @process.stderr, stderr, ->
|
||||
stderrClosed = true
|
||||
triggerExitCallback()
|
||||
|
||||
if exit
|
||||
processExited = false
|
||||
@process.on 'exit', (code) ->
|
||||
exitCode = code
|
||||
processExited = true
|
||||
triggerExitCallback()
|
||||
|
||||
@process.on 'error', (error) => @handleError(error)
|
||||
return
|
||||
|
||||
handleError: (error) ->
|
||||
handled = false
|
||||
handle = -> handled = true
|
||||
|
||||
@emitter.emit 'will-throw-error', {error, handle}
|
||||
|
||||
if error.code is 'ENOENT' and error.syscall.indexOf('spawn') is 0
|
||||
error = new Error("Failed to spawn command `#{@command}`. Make sure `#{@command}` is installed and on your PATH", error.path)
|
||||
error.name = 'BufferedProcessError'
|
||||
|
||||
throw error unless handled
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
// This file cannot be Coffeescript because it loads before the Coffeescript
|
||||
// interpreter. Note that it runs in both browser and renderer processes.
|
||||
|
||||
var ErrorReporter, raven, _;
|
||||
var ErrorReporter, raven, _, fs, path, app, os, remote;
|
||||
raven = require('raven');
|
||||
os = require('os');
|
||||
_ = require('underscore');
|
||||
fs = require('fs-plus');
|
||||
path = require('path');
|
||||
if (process.type === 'renderer') {
|
||||
remote = require('remote');
|
||||
app = remote.require('app');
|
||||
} else {
|
||||
app = require('app');
|
||||
}
|
||||
|
||||
tmpPath = app.getPath('temp');
|
||||
|
||||
module.exports = ErrorReporter = (function() {
|
||||
function ErrorReporter() {
|
||||
|
@ -17,6 +28,91 @@ module.exports = ErrorReporter = (function() {
|
|||
return console.log(e.response);
|
||||
});
|
||||
|
||||
// If we're the browser process, remove log files that are more than
|
||||
// two days old. These log files get pretty big because we're logging
|
||||
// so verbosely.
|
||||
if (process.type === 'browser') {
|
||||
fs.readdir(tmpPath, function(err, files) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
var logFilter = new RegExp("edgehill-[.0-9]*.log$");
|
||||
files.forEach(function(file) {
|
||||
if (logFilter.test(file) === true) {
|
||||
var filepath = path.join(tmpPath, file);
|
||||
fs.stat(filepath, function(err, stats) {
|
||||
var lastModified = new Date(stats['mtime']);
|
||||
var fileAge = Date.now() - lastModified.getTime();
|
||||
if (fileAge > (1000 * 60 * 60 * 24 * 2)) { // two days
|
||||
fs.unlink(filepath);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Open a file write stream to log output from this process
|
||||
var pid = process.pid;
|
||||
if (process.type === 'renderer') {
|
||||
pid = remote.process.pid + "." + process.pid;
|
||||
}
|
||||
var logpath = path.join(tmpPath, 'edgehill-' + pid + '.log');
|
||||
console.log("Streaming log data to "+logpath);
|
||||
|
||||
this.loghost = os.hostname();
|
||||
this.logstream = fs.createWriteStream(logpath, {
|
||||
flags: 'a',
|
||||
encoding: 'utf8',
|
||||
fd: null,
|
||||
mode: 0666
|
||||
});
|
||||
|
||||
// Override stdout and stderr to pipe their output to the file
|
||||
// in addition to calling through to the existing implementation
|
||||
function hook_process_output(channel, callback) {
|
||||
var old_write = process[channel].write;
|
||||
process[channel].write = (function(write) {
|
||||
return function(string, encoding, fd) {
|
||||
write.apply(process[channel], arguments)
|
||||
callback(string, encoding, fd)
|
||||
}
|
||||
})(process[channel].write)
|
||||
|
||||
// Return a function that can be used to undo this change
|
||||
return function() {
|
||||
process[channel].write = old_write
|
||||
};
|
||||
}
|
||||
|
||||
hook_process_output('stdout', function(string, encoding, fd) {
|
||||
self.appendLog.apply(self, [string]);
|
||||
});
|
||||
hook_process_output('stderr', function(string, encoding, fd) {
|
||||
self.appendLog.apply(self, [string]);
|
||||
});
|
||||
|
||||
this.shipLogsQueued = false;
|
||||
this.shipLogsTime = 0;
|
||||
|
||||
// Create a new console.debug option, which takes `true` (print)
|
||||
// or `false`, don't print in console as the first parameter.
|
||||
// This makes it easy for developers to turn on and off
|
||||
// "verbose console" mode.
|
||||
console.debug = function() {
|
||||
var args = [];
|
||||
var showIt = arguments[0];
|
||||
for (var ii = 1; ii < arguments.length; ii++) {
|
||||
args.push(arguments[ii]);
|
||||
}
|
||||
if ((self.dev === true) && (showIt === true)) {
|
||||
console.log.apply(this, args);
|
||||
}
|
||||
self.appendLog.apply(self, [args]);
|
||||
};
|
||||
|
||||
// Link to the appropriate error handlers for the browser
|
||||
// or renderer process
|
||||
if (process.type === 'renderer') {
|
||||
|
@ -48,6 +144,63 @@ module.exports = ErrorReporter = (function() {
|
|||
}
|
||||
}
|
||||
|
||||
ErrorReporter.prototype.appendLog = function(obj) {
|
||||
try {
|
||||
var message = JSON.stringify({
|
||||
host: this.loghost,
|
||||
timestamp: (new Date()).toISOString(),
|
||||
payload: obj
|
||||
})+"\n";
|
||||
|
||||
this.logstream.write(message, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.error("ErrorReporter: Unable to write to the log stream!" + err.toString());
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("ErrorReporter: Unable to write to the log stream." + err.toString());
|
||||
}
|
||||
};
|
||||
|
||||
ErrorReporter.prototype.shipLogs = function(reason) {
|
||||
var self = this;
|
||||
|
||||
this.shipLogsTime = Date.now();
|
||||
|
||||
if (!reason) {
|
||||
reason = "";
|
||||
}
|
||||
var logPattern = null;
|
||||
if (process.type === 'renderer') {
|
||||
logPattern = "edgehill-"+remote.process.pid+"[.0-9]*.log$";
|
||||
} else {
|
||||
logPattern = "edgehill-"+process.pid+"[.0-9]*.log$";
|
||||
}
|
||||
|
||||
console.log("ErrorReporter: Shipping Logs. " + reason);
|
||||
|
||||
Task = require('./task')
|
||||
ship = Task.once(fs.absolute('./tasks/ship-logs-task.coffee'), tmpPath, logPattern, function() {
|
||||
self.appendLog("ErrorReporter: Shipped Logs.");
|
||||
});
|
||||
};
|
||||
|
||||
ErrorReporter.prototype.shipLogsThrottled = function(reason) {
|
||||
if (!this.shipLogsQueued) {
|
||||
var timeSinceLogShip = Date.now() - this.shipLogsTime;
|
||||
if (timeSinceLogShip > 5000) {
|
||||
this.shipLogs(reason);
|
||||
} else {
|
||||
this.shipLogsQueued = true;
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
self.shipLogs(reason);
|
||||
self.shipLogsQueued = false;
|
||||
}, 5000 - timeSinceLogShip);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ErrorReporter.prototype.getVersion = function() {
|
||||
var _ref;
|
||||
return (typeof atom !== "undefined" && atom !== null ? atom.getVersion() : void 0) ||
|
||||
|
@ -61,13 +214,17 @@ module.exports = ErrorReporter = (function() {
|
|||
if (this.dev) {
|
||||
return;
|
||||
}
|
||||
return this.client.captureError(err, {
|
||||
|
||||
this.client.captureError(err, {
|
||||
extra: metadata,
|
||||
tags: {
|
||||
'platform': process.platform,
|
||||
'version': this.getVersion()
|
||||
}
|
||||
});
|
||||
|
||||
this.appendLog(err, metadata);
|
||||
this.shipLogsThrottled('Exception occurred');
|
||||
};
|
||||
|
||||
return ErrorReporter;
|
||||
|
|
|
@ -14,6 +14,8 @@ TargetWindows =
|
|||
Message =
|
||||
DATABASE_STORE_TRIGGER: 'db-store-trigger'
|
||||
|
||||
printToConsole = false
|
||||
|
||||
# Public: ActionBridge
|
||||
#
|
||||
# The ActionBridge has two responsibilities:
|
||||
|
@ -37,7 +39,6 @@ class ActionBridge
|
|||
@ipc = ipc
|
||||
@initiatorId = atom.getWindowType()
|
||||
@role = if atom.isMainWindow() then Role.ROOT else Role.SECONDARY
|
||||
@logging = false
|
||||
|
||||
# Listen for action bridge messages from other windows
|
||||
@ipc.on('action-bridge-message', @onIPCMessage)
|
||||
|
@ -63,7 +64,7 @@ class ActionBridge
|
|||
|
||||
|
||||
onIPCMessage: (initiatorId, name, json) =>
|
||||
console.log("#{@initiatorId} Action Bridge Received: #{name}") if @logging
|
||||
console.debug(printToConsole, "ActionBridge: #{@initiatorId} Action Bridge Received: #{name}")
|
||||
|
||||
# Inflate the arguments using the modelReviver to get actual
|
||||
# Models, tasks, etc. out of the JSON
|
||||
|
@ -96,7 +97,7 @@ class ActionBridge
|
|||
params.push(arg[0])
|
||||
json = JSON.stringify(params)
|
||||
|
||||
console.log("#{@initiatorId} Action Bridge Broadcasting: #{name}") if @logging
|
||||
console.debug(printToConsole, "ActionBridge: #{@initiatorId} Action Bridge Broadcasting: #{name}")
|
||||
@ipc.send("action-bridge-rebroadcast-to-#{target}", @initiatorId, name, json)
|
||||
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ class Actions
|
|||
@longPollConnected: ActionScopeMainWindow
|
||||
@longPollOffline: ActionScopeMainWindow
|
||||
@didMakeAPIRequest: ActionScopeMainWindow
|
||||
@sendFeedback: ActionScopeMainWindow
|
||||
|
||||
|
||||
###
|
||||
|
|
|
@ -259,7 +259,7 @@ Utils =
|
|||
# WARNING. This is a fairly expensive operation and should be used
|
||||
# sparingly.
|
||||
nodeIsVisible: (node) ->
|
||||
while node
|
||||
while node and node isnt window.document
|
||||
style = window.getComputedStyle(node)
|
||||
node = node.parentNode
|
||||
continue unless style?
|
||||
|
|
|
@ -5,6 +5,8 @@ Mixpanel = require 'mixpanel'
|
|||
Actions = require '../actions'
|
||||
NamespaceStore = require './namespace-store'
|
||||
|
||||
printToConsole = false
|
||||
|
||||
module.exports =
|
||||
AnalyticsStore = Reflux.createStore
|
||||
init: ->
|
||||
|
@ -61,14 +63,17 @@ AnalyticsStore = Reflux.createStore
|
|||
fileDownloaded: -> {}
|
||||
|
||||
coreGlobalActions: ->
|
||||
logout: -> {}
|
||||
fileAborted: (uploadData={}) -> {fileSize: uploadData.fileSize}
|
||||
fileUploaded: (uploadData={}) -> {fileSize: uploadData.fileSize}
|
||||
sendDraftSuccess: ({draftLocalId}) -> {draftLocalId: draftLocalId}
|
||||
|
||||
track: (action, data={}) ->
|
||||
# send to the analytics service
|
||||
@analytics.track(action, _.extend(data, namespaceId: NamespaceStore.current()?.id))
|
||||
|
||||
# send to the logs that we ship to LogStash
|
||||
console.debug(printToConsole, {action, data})
|
||||
|
||||
identify: ->
|
||||
namespace = NamespaceStore.current()
|
||||
if namespace
|
||||
|
|
|
@ -88,7 +88,8 @@ class ContactStore
|
|||
@_contactCache = contacts
|
||||
@trigger()
|
||||
resolve()
|
||||
.catch(reject)
|
||||
.catch (err) ->
|
||||
console.warn("Request for Contacts failed. #{err}")
|
||||
_refreshCache: _.debounce(ContactStore::__refreshCache, 20)
|
||||
|
||||
_onDatabaseChanged: (change) =>
|
||||
|
|
|
@ -20,8 +20,7 @@ ipc = require 'ipc'
|
|||
CoffeeHelpers = require '../coffee-helpers'
|
||||
|
||||
silent = atom.getLoadSettings().isSpec
|
||||
verboseFilter = (query) ->
|
||||
false
|
||||
printToConsole = false
|
||||
|
||||
# The DatabaseProxy dispatches queries to the Browser process via IPC and listens
|
||||
# for results. It maintains a hash of `queryRecords` representing queries that are
|
||||
|
@ -37,8 +36,16 @@ class DatabaseProxy
|
|||
record = @queryRecords[queryKey]
|
||||
return unless record
|
||||
|
||||
{callback, options} = record
|
||||
console.timeStamp("DB END #{queryKey}. #{result?.length} chars")
|
||||
{callback, options, start, query} = record
|
||||
|
||||
duration = Date.now() - start
|
||||
metadata =
|
||||
duration: duration
|
||||
result_length: result?.length
|
||||
|
||||
console.debug(printToConsole, "DatabaseStore: #{query}", metadata)
|
||||
if duration > 300
|
||||
atom.errorReporter.shipLogs("Poor Query Performance")
|
||||
|
||||
waits = Promise.resolve()
|
||||
waits = PriorityUICoordinator.settle unless options.evaluateImmediately
|
||||
|
@ -53,10 +60,10 @@ class DatabaseProxy
|
|||
queryKey = "#{@windowId}-#{@queryId}"
|
||||
@queryRecords[queryKey] = {
|
||||
callback: callback,
|
||||
options: options
|
||||
query: query,
|
||||
options: options,
|
||||
start: Date.now()
|
||||
}
|
||||
console.timeStamp("DB SEND #{queryKey}: #{query}")
|
||||
console.log(query,values) if verboseFilter(query)
|
||||
ipc.send('database-query', {@databasePath, queryKey, query, values})
|
||||
|
||||
# DatabasePromiseTransaction converts the callback syntax of the Database
|
||||
|
@ -71,7 +78,7 @@ class DatabasePromiseTransaction
|
|||
# Wrap any user-provided success callback in one that checks query time
|
||||
callback = (err, result) =>
|
||||
if err
|
||||
console.log("Query #{query}, #{JSON.stringify(values)} failed #{err.message}")
|
||||
console.error("DatabaseStore: Query #{query}, #{JSON.stringify(values)} failed #{err.message}")
|
||||
queryFailure(err) if queryFailure
|
||||
@_reject(err)
|
||||
else
|
||||
|
|
|
@ -103,7 +103,8 @@ MetadataStore = Reflux.createStore
|
|||
@_metadata[metadatum.type][metadatum.publicId][metadatum.key] = metadatum.value
|
||||
@trigger()
|
||||
resolve()
|
||||
.catch(reject)
|
||||
.catch (err) ->
|
||||
console.warn("Request for Metadata failed. #{err}")
|
||||
|
||||
_onNamespaceChanged: ->
|
||||
@_namespaceId = NamespaceStore.current()?.id
|
||||
|
|
|
@ -35,6 +35,8 @@ class NamespaceStore
|
|||
@_current = current
|
||||
@_namespaces = namespaces
|
||||
@trigger(@)
|
||||
.catch (err) =>
|
||||
console.warn("Request for Namespaces failed. #{err}")
|
||||
|
||||
# Inbound Events
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ registerBuiltins = (devMode) ->
|
|||
cache.builtins.atom = atomCoffeePath if fs.isFileSync(atomCoffeePath)
|
||||
cache.builtins.atom ?= path.join(cache.resourcePath, 'exports', 'atom.js')
|
||||
|
||||
atomShellRoot = path.join(process.resourcesPath, 'atom')
|
||||
atomShellRoot = path.join(process.resourcesPath, 'atom.asar')
|
||||
|
||||
commonRoot = path.join(atomShellRoot, 'common', 'api', 'lib')
|
||||
commonBuiltins = ['callbacks-registry', 'clipboard', 'crash-reporter', 'screen', 'shell']
|
||||
|
|
|
@ -3,6 +3,16 @@ _ = _.extend(_, require('./space-pen-utils'))
|
|||
SpacePen = require 'space-pen'
|
||||
{Subscriber} = require 'emissary'
|
||||
|
||||
###
|
||||
Edgehill Note:
|
||||
|
||||
I want this file gone—plan is to slowly delete stuff below as we clean spacepen
|
||||
and it's helpers out of the project.
|
||||
|
||||
- Ben
|
||||
###
|
||||
|
||||
|
||||
Subscriber.includeInto(SpacePen.View)
|
||||
|
||||
jQuery = SpacePen.jQuery
|
||||
|
@ -94,65 +104,6 @@ jQuery.contains = (a, b) ->
|
|||
|
||||
JQueryContains.call(this, a, b)
|
||||
|
||||
tooltipDefaults =
|
||||
delay:
|
||||
show: 1000
|
||||
hide: 100
|
||||
container: 'body'
|
||||
html: true
|
||||
placement: 'auto top'
|
||||
viewportPadding: 2
|
||||
|
||||
humanizeKeystrokes = (keystroke) ->
|
||||
keystrokes = keystroke.split(' ')
|
||||
keystrokes = (_.humanizeKeystroke(stroke) for stroke in keystrokes)
|
||||
keystrokes.join(' ')
|
||||
|
||||
getKeystroke = (bindings) ->
|
||||
if bindings?.length
|
||||
"<span class=\"keystroke\">#{humanizeKeystrokes(bindings[0].keystrokes)}</span>"
|
||||
else
|
||||
''
|
||||
|
||||
requireBootstrapTooltip = _.once ->
|
||||
atom.requireWithGlobals('bootstrap/js/tooltip', {jQuery})
|
||||
|
||||
# options from http://getbootstrap.com/javascript/#tooltips
|
||||
jQuery.fn.setTooltip = (tooltipOptions, {command, commandElement}={}) ->
|
||||
requireBootstrapTooltip()
|
||||
|
||||
tooltipOptions = {title: tooltipOptions} if _.isString(tooltipOptions)
|
||||
|
||||
if commandElement
|
||||
bindings = atom.keymaps.findKeyBindings(command: command, target: commandElement[0])
|
||||
else if command
|
||||
bindings = atom.keymaps.findKeyBindings(command: command)
|
||||
|
||||
tooltipOptions.title = "#{tooltipOptions.title} #{getKeystroke(bindings)}"
|
||||
|
||||
@tooltip(jQuery.extend({}, tooltipDefaults, tooltipOptions))
|
||||
|
||||
jQuery.fn.hideTooltip = ->
|
||||
tip = @data('bs.tooltip')
|
||||
if tip
|
||||
tip.leave(currentTarget: this)
|
||||
tip.hide()
|
||||
|
||||
jQuery.fn.destroyTooltip = ->
|
||||
@hideTooltip()
|
||||
requireBootstrapTooltip()
|
||||
@tooltip('destroy')
|
||||
|
||||
# Hide tooltips when window is resized
|
||||
jQuery(document.body).on 'show.bs.tooltip', ({target}) ->
|
||||
windowHandler = -> jQuery(target).hideTooltip()
|
||||
jQuery(window).one('resize', windowHandler)
|
||||
jQuery(target).one 'hide.bs.tooltip', ->
|
||||
jQuery(window).off('resize', windowHandler)
|
||||
|
||||
jQuery.fn.setTooltip.getKeystroke = getKeystroke
|
||||
jQuery.fn.setTooltip.humanizeKeystrokes = humanizeKeystrokes
|
||||
|
||||
Object.defineProperty jQuery.fn, 'element', get: -> @[0]
|
||||
|
||||
module.exports = SpacePen
|
||||
|
|
|
@ -10,6 +10,14 @@ setupGlobals = ->
|
|||
trace: ->
|
||||
global.__defineGetter__ 'console', -> console
|
||||
|
||||
fs = require 'fs'
|
||||
fs.existsSync = (path) ->
|
||||
try
|
||||
fs.accessSync(path)
|
||||
return true
|
||||
catch
|
||||
return false
|
||||
|
||||
global.document =
|
||||
createElement: ->
|
||||
setAttribute: ->
|
||||
|
@ -24,7 +32,7 @@ setupGlobals = ->
|
|||
|
||||
global.emit = (event, args...) ->
|
||||
process.send({event, args})
|
||||
global.navigator = {userAgent}
|
||||
global.navigator = {userAgent: userAgent}
|
||||
global.window = global
|
||||
|
||||
handleEvents = ->
|
||||
|
@ -41,6 +49,14 @@ handleEvents = ->
|
|||
result = handler.bind({async})(args...)
|
||||
emit('task:completed', result) unless isAsync
|
||||
|
||||
setupDeprecations = ->
|
||||
Grim = require 'grim'
|
||||
Grim.on 'updated', ->
|
||||
deprecations = Grim.getDeprecations().map (deprecation) -> deprecation.serialize()
|
||||
Grim.clearDeprecations()
|
||||
emit('task:deprecations', deprecations)
|
||||
|
||||
setupGlobals()
|
||||
handleEvents()
|
||||
setupDeprecations()
|
||||
handler = require(taskPath)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
_ = require 'underscore'
|
||||
{fork} = require 'child_process'
|
||||
{Emitter} = require 'emissary'
|
||||
Grim = require 'grim'
|
||||
|
||||
# Extended: Run a node script in a separate process.
|
||||
#
|
||||
|
@ -78,12 +79,15 @@ class Task
|
|||
taskPath = require.resolve(taskPath)
|
||||
taskPath = taskPath.replace(/\\/g, "\\\\")
|
||||
|
||||
env = _.extend({}, process.env, {taskPath, userAgent: navigator.userAgent})
|
||||
@childProcess = fork '--eval', [bootstrap], {env, cwd: __dirname}
|
||||
env = _.extend({}, process.env, {taskPath, userAgent: process.env.userAgent})
|
||||
@childProcess = fork '--eval', [bootstrap], {env, silent: true}
|
||||
|
||||
@on "task:log", -> console.log(arguments...)
|
||||
@on "task:warn", -> console.warn(arguments...)
|
||||
@on "task:error", -> console.error(arguments...)
|
||||
@on "task:deprecations", (deprecations) ->
|
||||
Grim.addSerializedDeprecation(deprecation) for deprecation in deprecations
|
||||
return
|
||||
@on "task:completed", (args...) => @callback?(args...)
|
||||
|
||||
@handleEvents()
|
||||
|
@ -93,6 +97,11 @@ class Task
|
|||
@childProcess.removeAllListeners()
|
||||
@childProcess.on 'message', ({event, args}) =>
|
||||
@emit(event, args...) if @childProcess?
|
||||
# Catch the errors that happened before task-bootstrap.
|
||||
@childProcess.stdout.on 'data', (data) ->
|
||||
console.log data.toString()
|
||||
@childProcess.stderr.on 'data', (data) ->
|
||||
console.error data.toString()
|
||||
|
||||
# Public: Starts the task.
|
||||
#
|
||||
|
|
55
src/tasks/ship-logs-task.coffee
Normal file
55
src/tasks/ship-logs-task.coffee
Normal file
|
@ -0,0 +1,55 @@
|
|||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
request = require 'request'
|
||||
|
||||
module.exports = (dir, regexPattern) ->
|
||||
callback = @async()
|
||||
|
||||
console.log("Running log ship: #{dir}, #{regexPattern}")
|
||||
|
||||
fs.readdir dir, (err, files) ->
|
||||
console.log("readdir error: #{err}") if err
|
||||
logs = []
|
||||
logFilter = new RegExp(regexPattern)
|
||||
for file in files
|
||||
if logFilter.test(file)
|
||||
filepath = path.join(dir, file)
|
||||
stats = fs.statSync(filepath)
|
||||
logs.push(filepath) if stats["size"] > 0
|
||||
|
||||
remaining = 0
|
||||
finished = ->
|
||||
remaining -= 1
|
||||
if remaining is 0
|
||||
callback()
|
||||
|
||||
if logs.length is 0
|
||||
console.log("No logs found to upload.")
|
||||
callback()
|
||||
console.log("Callback.")
|
||||
return
|
||||
|
||||
console.log("Uploading #{logs} to S3")
|
||||
|
||||
# Note: These credentials are only good for uploading to this
|
||||
# specific bucket and can't be used for anything else.
|
||||
AWS = require 'aws-sdk'
|
||||
AWS.config.update
|
||||
accessKeyId: 'AKIAIEGVDSVLK3Z7UVFA',
|
||||
secretAccessKey: '5ZNFMrjO3VUxpw4F9Y5xXPtVHgriwiWof4sFEsjQ'
|
||||
|
||||
bucket = new AWS.S3({params: {Bucket: 'edgehill-client-logs'}})
|
||||
uploadTime = Date.now()
|
||||
|
||||
logs.forEach (log) ->
|
||||
stream = fs.createReadStream(log, {flags: 'r'})
|
||||
key = "#{uploadTime}-#{path.basename(log)}"
|
||||
params = {Key: key, Body: stream}
|
||||
remaining += 1
|
||||
bucket.upload params, (err, data) ->
|
||||
if err
|
||||
console.log("Error uploading #{key}: #{err.toString()}")
|
||||
else
|
||||
console.log("Successfully uploaded #{key}")
|
||||
fs.truncate(log)
|
||||
finished()
|
|
@ -31,6 +31,10 @@ class WindowEventHandler
|
|||
when 'update-available'
|
||||
atom.updateAvailable(detail)
|
||||
|
||||
when 'send-feedback'
|
||||
Actions = require './flux/actions'
|
||||
Actions.sendFeedback()
|
||||
|
||||
@subscribe ipc, 'command', (command, args...) ->
|
||||
activeElement = document.activeElement
|
||||
# Use the workspace element view if body has focus
|
||||
|
|
Loading…
Add table
Reference in a new issue