Merge branch 'master' into portable-mode

Conflicts:
	src/browser/main.coffee
This commit is contained in:
Dave Rael
2015-10-06 14:28:10 -06:00
200 changed files with 4902 additions and 17171 deletions

View File

@@ -1,2 +1 @@
spec/fixtures
benchmark/fixtures

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ npm-debug.log
debug.log
/tags
/atom-shell/
/electron/
docs/output
docs/includes
spec/fixtures/evil-files/

View File

@@ -8,15 +8,19 @@ branches:
env:
global:
- ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4
- NODE_VERSION=0.12
compiler: clang
matrix:
include:
- os: linux
env: NODE_VERSION=0.12
- os: linux
env: NODE_VERSION=4
- os: osx
env: ATOM_SPECS_TASK=core
env: ATOM_SPECS_TASK=core NODE_VERSION=0.12
- os: osx
env: ATOM_SPECS_TASK=packages
env: ATOM_SPECS_TASK=packages NODE_VERSION=0.12
sudo: false

View File

@@ -234,6 +234,7 @@ Please open an issue on `atom/atom` if you have suggestions for new labels, and
| `installer` | [search][search-atom-repo-label-installer] | [search][search-atom-org-label-installer] | Related to the Atom installers for different OSes. |
| `auto-updater` | [search][search-atom-repo-label-auto-updater] | [search][search-atom-org-label-auto-updater] | Related to the auto-updater for different OSes. |
| `deprecation-help` | [search][search-atom-repo-label-deprecation-help] | [search][search-atom-org-label-deprecation-help] | Issues for helping package authors remove usage of deprecated APIs in packages. |
| `electron` | [search][search-atom-repo-label-electron] | [search][search-atom-org-label-electron] | Issues that require changes to [Electron](https://electron.atom.io) to fix or implement. |
#### Core Team Project Management
@@ -329,6 +330,8 @@ Please open an issue on `atom/atom` if you have suggestions for new labels, and
[search-atom-org-label-auto-updater]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aauto-updater
[search-atom-repo-label-deprecation-help]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Adeprecation-help
[search-atom-org-label-deprecation-help]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Adeprecation-help
[search-atom-repo-label-electron]: https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Fatom+is%3Aopen+label%3Aelectron
[search-atom-org-label-electron]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aelectron
[search-atom-repo-label-on-deck]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aon-deck
[search-atom-org-label-on-deck]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aon-deck
[search-atom-repo-label-in-progress]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ain-progress

View File

@@ -6,6 +6,6 @@
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "1.0.4"
"atom-package-manager": "1.1.1"
}
}

21
atom.sh
View File

@@ -11,6 +11,12 @@ else
exit 1
fi
if [ "$(basename $0)" == 'atom-beta' ]; then
BETA_VERSION=true
else
BETA_VERSION=
fi
while getopts ":wtfvh-:" opt; do
case "$opt" in
-)
@@ -45,7 +51,11 @@ if [ $REDIRECT_STDERR ]; then
fi
if [ $OS == 'Mac' ]; then
ATOM_APP_NAME=Atom.app
if [ -n "$BETA_VERSION" ]; then
ATOM_APP_NAME="Atom Beta.app"
else
ATOM_APP_NAME="Atom.app"
fi
if [ -z "${ATOM_PATH}" ]; then
# If ATOM_PATH isnt set, check /Applications and then ~/Applications for Atom.app
@@ -74,9 +84,14 @@ if [ $OS == 'Mac' ]; then
elif [ $OS == 'Linux' ]; then
SCRIPT=$(readlink -f "$0")
USR_DIRECTORY=$(readlink -f $(dirname $SCRIPT)/..)
ATOM_PATH="$USR_DIRECTORY/share/atom/atom"
ATOM_HOME="${ATOM_HOME:-$HOME/.atom}"
if [ -n "$BETA_VERSION" ]; then
ATOM_PATH="$USR_DIRECTORY/share/atom-beta/atom"
else
ATOM_PATH="$USR_DIRECTORY/share/atom/atom"
fi
ATOM_HOME="${ATOM_HOME:-$HOME/.atom}"
mkdir -p "$ATOM_HOME"
: ${TMPDIR:=/tmp}

View File

@@ -1,12 +0,0 @@
require '../src/window'
Atom = require '../src/atom'
window.atom = Atom.loadOrCreate('spec')
atom.show() unless atom.getLoadSettings().exitWhenDone
window.atom = atom
{runSpecSuite} = require '../spec/jasmine-helper'
atom.openDevTools()
document.title = "Benchmark Suite"
runSpecSuite('../benchmark/benchmark-suite', atom.getLoadSettings().logFile)

View File

@@ -1,115 +0,0 @@
require '../spec/spec-helper'
path = require 'path'
{$} = require '../src/space-pen-extensions'
{Point} = require 'atom'
_ = require 'underscore-plus'
fs = require 'fs-plus'
Project = require '../src/project'
TokenizedBuffer = require '../src/tokenized-buffer'
defaultCount = 100
window.pbenchmark = (args...) -> window.benchmark(args..., profile: true)
window.fbenchmark = (args...) -> window.benchmark(args..., focused: true)
window.fpbenchmark = (args...) -> window.benchmark(args..., profile: true, focused: true)
window.pfbenchmark = window.fpbenchmark
window.benchmarkFixturesProject = new Project(path.join(__dirname, 'fixtures'))
beforeEach ->
window.project = window.benchmarkFixturesProject
jasmine.unspy(window, 'setTimeout')
jasmine.unspy(window, 'clearTimeout')
jasmine.unspy(TokenizedBuffer::, 'tokenizeInBackground')
window.benchmark = (args...) ->
description = args.shift()
if typeof args[0] is 'number'
count = args.shift()
else
count = defaultCount
[fn, options] = args
{profile, focused} = (options ? {})
method = if focused then fit else it
method description, ->
total = measure ->
console.profile(description) if profile
_.times count, fn
console.profileEnd(description) if profile
avg = total / count
fullname = @getFullName().replace(/\s|\.$/g, "")
report = "#{fullname}: #{total} / #{count} = #{avg}ms"
console.log(report)
if atom.getLoadSettings().exitWhenDone
url = "https://github.com/_stats"
data = [type: 'timing', metric: "atom.#{fullname}", ms: avg]
$.ajax url,
async: false
data: JSON.stringify(data)
error: (args...) ->
console.log "Failed to send atom.#{fullname}\n#{JSON.stringify(args)}"
window.measure = (fn) ->
start = new Date().getTime()
fn()
new Date().getTime() - start
window.waitsForPromise = (fn) ->
window.waitsFor (moveOn) ->
fn().done(moveOn)
window.keyIdentifierForKey = (key) ->
if key.length > 1 # named key
key
else
charCode = key.toUpperCase().charCodeAt(0)
"U+00" + charCode.toString(16)
window.keydownEvent = (key, properties={}) ->
$.Event "keydown", _.extend({originalEvent: {keyIdentifier: keyIdentifierForKey(key)}}, properties)
window.clickEvent = (properties={}) ->
$.Event "click", properties
window.mouseEvent = (type, properties) ->
if properties.point
{point, editorView} = properties
{top, left} = @pagePixelPositionForPoint(editorView, point)
properties.pageX = left + 1
properties.pageY = top + 1
properties.originalEvent ?= {detail: 1}
$.Event type, properties
window.mousedownEvent = (properties={}) ->
window.mouseEvent('mousedown', properties)
window.mousemoveEvent = (properties={}) ->
window.mouseEvent('mousemove', properties)
window.pagePixelPositionForPoint = (editorView, point) ->
point = Point.fromObject point
top = editorView.lines.offset().top + point.row * editorView.lineHeight
left = editorView.lines.offset().left + point.column * editorView.charWidth - editorView.lines.scrollLeft()
{top, left}
window.seteditorViewWidthInChars = (editorView, widthInChars, charWidth=editorView.charWidth) ->
editorView.width(charWidth * widthInChars + editorView.lines.position().left)
$.fn.resultOfTrigger = (type) ->
event = $.Event(type)
this.trigger(event)
event.result
$.fn.enableKeymap = ->
@on 'keydown', (e) -> window.keymap.handleKeyEvent(e)
$.fn.attachToDom = ->
$('#jasmine-content').append(this)
$.fn.textInput = (data) ->
event = document.createEvent 'TextEvent'
event.initTextEvent('textInput', true, true, window, data)
this.each -> this.dispatchEvent(event)

View File

@@ -1,219 +0,0 @@
require './benchmark-helper'
{$} = require '../src/space-pen-extensions'
_ = require 'underscore-plus'
{WorkspaceView} = require 'atom'
TokenizedBuffer = require '../src/tokenized-buffer'
describe "editorView.", ->
editorView = null
beforeEach ->
atom.workspaceViewParentSelector = '#jasmine-content'
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
atom.workspaceView.attachToDom()
atom.workspaceView.width(1024)
atom.workspaceView.height(768)
atom.workspaceView.openSync()
editorView = atom.workspaceView.getActiveView()
afterEach ->
if editorView.pendingDisplayUpdate
waitsFor "editor to finish rendering", (done) ->
editorView.on 'editor:display-updated', done
describe "keymap.", ->
event = null
beforeEach ->
event = keydownEvent('x', target: editorView.hiddenInput[0])
benchmark "keydown-event-with-no-binding", 10, ->
keymap.handleKeyEvent(event)
describe "opening-buffers.", ->
benchmark "300-line-file.", ->
buffer = project.bufferForPathSync('medium.coffee')
describe "empty-file.", ->
benchmark "insert-delete", ->
editorView.insertText('x')
editorView.backspace()
describe "300-line-file.", ->
beforeEach ->
atom.workspaceView.openSync('medium.coffee')
describe "at-begining.", ->
benchmark "insert-delete", ->
editorView.insertText('x')
editorView.backspace()
benchmark "insert-delete-rehighlight", ->
editorView.insertText('"')
editorView.backspace()
describe "at-end.", ->
beforeEach ->
editorView.moveToBottom()
benchmark "insert-delete", ->
editorView.insertText('"')
editorView.backspace()
describe "empty-vs-set-innerHTML.", ->
[firstRow, lastRow] = []
beforeEach ->
firstRow = editorView.getModel().getFirstVisibleScreenRow()
lastRow = editorView.getModel().getLastVisibleScreenRow()
benchmark "build-gutter-html.", 1000, ->
editorView.gutter.renderLineNumbers(null, firstRow, lastRow)
benchmark "set-innerHTML.", 1000, ->
editorView.gutter.renderLineNumbers(null, firstRow, lastRow)
editorView.gutter.lineNumbers[0].innerHtml = ''
benchmark "empty.", 1000, ->
editorView.gutter.renderLineNumbers(null, firstRow, lastRow)
editorView.gutter.lineNumbers.empty()
describe "positionLeftForLineAndColumn.", ->
line = null
beforeEach ->
editorView.scrollTop(2000)
editorView.resetDisplay()
line = editorView.lineElementForScreenRow(106)[0]
describe "one-line.", ->
beforeEach ->
editorView.clearCharacterWidthCache()
benchmark "uncached", 5000, ->
editorView.positionLeftForLineAndColumn(line, 106, 82)
editorView.clearCharacterWidthCache()
benchmark "cached", 5000, ->
editorView.positionLeftForLineAndColumn(line, 106, 82)
describe "multiple-lines.", ->
[firstRow, lastRow] = []
beforeEach ->
firstRow = editorView.getModel().getFirstVisibleScreenRow()
lastRow = editorView.getModel().getLastVisibleScreenRow()
benchmark "cache-entire-visible-area", 100, ->
for i in [firstRow..lastRow]
line = editorView.lineElementForScreenRow(i)[0]
editorView.positionLeftForLineAndColumn(line, i, Math.max(0, editorView.getModel().lineTextForBufferRow(i).length))
describe "text-rendering.", ->
beforeEach ->
editorView.scrollTop(2000)
benchmark "resetDisplay", 50, ->
editorView.resetDisplay()
benchmark "htmlForScreenRows", 1000, ->
lastRow = editorView.getLastScreenRow()
editorView.htmlForScreenRows(0, lastRow)
benchmark "htmlForScreenRows.htmlParsing", 50, ->
lastRow = editorView.getLastScreenRow()
html = editorView.htmlForScreenRows(0, lastRow)
div = document.createElement('div')
div.innerHTML = html
describe "gutter-api.", ->
describe "getLineNumberElementsForClass.", ->
beforeEach ->
editorView.gutter.addClassToLine(20, 'omgwow')
editorView.gutter.addClassToLine(40, 'omgwow')
benchmark "DOM", 20000, ->
editorView.gutter.getLineNumberElementsForClass('omgwow')
benchmark "getLineNumberElement.DOM", 20000, ->
editorView.gutter.getLineNumberElement(12)
benchmark "toggle-class", 2000, ->
editorView.gutter.addClassToLine(40, 'omgwow')
editorView.gutter.removeClassFromLine(40, 'omgwow')
describe "find-then-unset.", ->
classes = ['one', 'two', 'three', 'four']
benchmark "single-class", 200, ->
editorView.gutter.addClassToLine(30, 'omgwow')
editorView.gutter.addClassToLine(40, 'omgwow')
editorView.gutter.removeClassFromAllLines('omgwow')
benchmark "multiple-class", 200, ->
editorView.gutter.addClassToLine(30, 'one')
editorView.gutter.addClassToLine(30, 'two')
editorView.gutter.addClassToLine(40, 'two')
editorView.gutter.addClassToLine(40, 'three')
editorView.gutter.addClassToLine(40, 'four')
for klass in classes
editorView.gutter.removeClassFromAllLines(klass)
describe "line-htmlification.", ->
div = null
html = null
beforeEach ->
lastRow = editorView.getLastScreenRow()
html = editorView.htmlForScreenRows(0, lastRow)
div = document.createElement('div')
benchmark "setInnerHTML", 1, ->
div.innerHTML = html
describe "9000-line-file.", ->
benchmark "opening.", 5, ->
atom.workspaceView.openSync('huge.js')
describe "after-opening.", ->
beforeEach ->
atom.workspaceView.openSync('huge.js')
benchmark "moving-to-eof.", 1, ->
editorView.moveToBottom()
describe "on-first-line.", ->
benchmark "inserting-newline", 5, ->
editorView.insertNewline()
describe "on-last-visible-line.", ->
beforeEach ->
editorView.setCursorScreenPosition([editorView.getLastVisibleScreenRow(), 0])
benchmark "move-down-and-scroll", 300, ->
editorView.trigger 'move-down'
describe "at-eof.", ->
endPosition = null
beforeEach ->
editorView.moveToBottom()
endPosition = editorView.getCursorScreenPosition()
benchmark "move-to-beginning-of-word", ->
editorView.moveToBeginningOfWord()
editorView.setCursorScreenPosition(endPosition)
benchmark "insert", ->
editorView.insertText('x')
describe "TokenizedBuffer.", ->
describe "coffee-script-grammar.", ->
[languageMode, buffer] = []
beforeEach ->
editor = benchmarkFixturesProject.openSync('medium.coffee')
{languageMode, buffer} = editor
benchmark "construction", 20, ->
new TokenizedBuffer(buffer, {languageMode, tabLength: 2})

View File

@@ -1,56 +0,0 @@
#!/usr/bin/env coffee
{spawn, exec} = require 'child_process'
fs = require 'fs'
os = require 'os'
path = require 'path'
_ = require 'underscore-plus'
temp = require 'temp'
directoryToOpen = temp.mkdirSync('browser-process-startup-')
socketPath = path.join(os.tmpdir(), "atom-#{process.env.USER}.sock")
numberOfRuns = 10
deleteSocketFile = ->
try
fs.unlinkSync(socketPath) if fs.existsSync(socketPath)
catch error
console.error(error)
launchAtom = (callback) ->
deleteSocketFile()
cmd = 'atom'
args = ['--safe', '--new-window', '--foreground', directoryToOpen]
atomProcess = spawn(cmd, args)
output = ''
startupTimes = []
dataListener = (data) ->
output += data
if match = /App load time: (\d+)/.exec(output)
startupTime = parseInt(match[1])
atomProcess.stderr.removeListener 'data', dataListener
atomProcess.kill()
exec 'pkill -9 Atom', (error) ->
console.error(error) if error?
callback(startupTime)
atomProcess.stderr.on 'data', dataListener
startupTimes = []
collector = (startupTime) ->
startupTimes.push(startupTime)
if startupTimes.length < numberOfRuns
launchAtom(collector)
else
maxTime = _.max(startupTimes)
minTime = _.min(startupTimes)
totalTime = startupTimes.reduce (previousValue=0, currentValue) -> previousValue + currentValue
console.log "Startup Runs: #{startupTimes.length}"
console.log "First run time: #{startupTimes[0]}ms"
console.log "Max time: #{maxTime}ms"
console.log "Min time: #{minTime}ms"
console.log "Average time: #{Math.round(totalTime/startupTimes.length)}ms"
launchAtom(collector)

File diff suppressed because it is too large Load Diff

View File

@@ -1,240 +0,0 @@
# **Docco** is a quick-and-dirty, hundred-line-long, literate-programming-style
# documentation generator. It produces HTML
# that displays your comments alongside your code. Comments are passed through
# [Markdown](http://daringfireball.net/projects/markdown/syntax), and code is
# passed through [Pygments](http://pygments.org/) syntax highlighting.
# This page is the result of running Docco against its own source file.
#
# If you install Docco, you can run it from the command-line:
#
# docco src/*.coffee
#
# ...will generate an HTML documentation page for each of the named source files,
# with a menu linking to the other pages, saving it into a `docs` folder.
#
# The [source for Docco](http://github.com/jashkenas/docco) is available on GitHub,
# and released under the MIT license.
#
# To install Docco, first make sure you have [Node.js](http://nodejs.org/),
# [Pygments](http://pygments.org/) (install the latest dev version of Pygments
# from [its Mercurial repo](http://dev.pocoo.org/hg/pygments-main)), and
# [CoffeeScript](http://coffeescript.org/). Then, with NPM:
#
# sudo npm install -g docco
#
# Docco can be used to process CoffeeScript, JavaScript, Ruby, Python, or TeX files.
# Only single-line comments are processed -- block comments are ignored.
#
#### Partners in Crime:
#
# * If **Node.js** doesn't run on your platform, or you'd prefer a more
# convenient package, get [Ryan Tomayko](http://github.com/rtomayko)'s
# [Rocco](http://rtomayko.github.com/rocco/rocco.html), the Ruby port that's
# available as a gem.
#
# * If you're writing shell scripts, try
# [Shocco](http://rtomayko.github.com/shocco/), a port for the **POSIX shell**,
# also by Mr. Tomayko.
#
# * If Python's more your speed, take a look at
# [Nick Fitzgerald](http://github.com/fitzgen)'s [Pycco](http://fitzgen.github.com/pycco/).
#
# * For **Clojure** fans, [Fogus](http://blog.fogus.me/)'s
# [Marginalia](http://fogus.me/fun/marginalia/) is a bit of a departure from
# "quick-and-dirty", but it'll get the job done.
#
# * **Lua** enthusiasts can get their fix with
# [Robert Gieseke](https://github.com/rgieseke)'s [Locco](http://rgieseke.github.com/locco/).
#
# * And if you happen to be a **.NET**
# aficionado, check out [Don Wilson](https://github.com/dontangg)'s
# [Nocco](http://dontangg.github.com/nocco/).
#### Main Documentation Generation Functions
# Generate the documentation for a source file by reading it in, splitting it
# up into comment/code sections, highlighting them for the appropriate language,
# and merging them into an HTML template.
generate_documentation = (source, callback) ->
fs.readFile source, "utf-8", (error, code) ->
throw error if error
sections = parse source, code
highlight source, sections, ->
generate_html source, sections
callback()
# Given a string of source code, parse out each comment and the code that
# follows it, and create an individual **section** for it.
# Sections take the form:
#
# {
# docs_text: ...
# docs_html: ...
# code_text: ...
# code_html: ...
# }
#
parse = (source, code) ->
lines = code.split '\n'
sections = []
language = get_language source
has_code = docs_text = code_text = ''
save = (docs, code) ->
sections.push docs_text: docs, code_text: code
for line in lines
if line.match(language.comment_matcher) and not line.match(language.comment_filter)
if has_code
save docs_text, code_text
has_code = docs_text = code_text = ''
docs_text += line.replace(language.comment_matcher, '') + '\n'
else
has_code = yes
code_text += line + '\n'
save docs_text, code_text
sections
# Highlights a single chunk of CoffeeScript code, using **Pygments** over stdio,
# and runs the text of its corresponding comment through **Markdown**, using
# [Showdown.js](http://attacklab.net/showdown/).
#
# We process the entire file in a single call to Pygments by inserting little
# marker comments between each section and then splitting the result string
# wherever our markers occur.
highlight = (source, sections, callback) ->
language = get_language source
pygments = spawn 'pygmentize', ['-l', language.name, '-f', 'html', '-O', 'encoding=utf-8,tabsize=2']
output = ''
pygments.stderr.addListener 'data', (error) ->
console.error error.toString() if error
pygments.stdin.addListener 'error', (error) ->
console.error "Could not use Pygments to highlight the source."
process.exit 1
pygments.stdout.addListener 'data', (result) ->
output += result if result
pygments.addListener 'exit', ->
output = output.replace(highlight_start, '').replace(highlight_end, '')
fragments = output.split language.divider_html
for section, i in sections
section.code_html = highlight_start + fragments[i] + highlight_end
section.docs_html = showdown.makeHtml section.docs_text
callback()
if pygments.stdin.writable
pygments.stdin.write((section.code_text for section in sections).join(language.divider_text))
pygments.stdin.end()
# Once all of the code is finished highlighting, we can generate the HTML file
# and write out the documentation. Pass the completed sections into the template
# found in `resources/docco.jst`
generate_html = (source, sections) ->
title = path.basename source
dest = destination source
html = docco_template {
title: title, sections: sections, sources: sources, path: path, destination: destination
}
console.log "docco: #{source} -> #{dest}"
fs.writeFile dest, html
#### Helpers & Setup
# Require our external dependencies, including **Showdown.js**
# (the JavaScript implementation of Markdown).
fs = require 'fs-utils'
path = require 'path'
showdown = require('./../vendor/showdown').Showdown
{spawn, exec} = require 'child_process'
# A list of the languages that Docco supports, mapping the file extension to
# the name of the Pygments lexer and the symbol that indicates a comment. To
# add another language to Docco's repertoire, add it here.
languages =
'.coffee':
name: 'coffee-script', symbol: '#'
'.js':
name: 'javascript', symbol: '//'
'.rb':
name: 'ruby', symbol: '#'
'.py':
name: 'python', symbol: '#'
'.tex':
name: 'tex', symbol: '%'
'.latex':
name: 'tex', symbol: '%'
'.c':
name: 'c', symbol: '//'
'.h':
name: 'c', symbol: '//'
# Build out the appropriate matchers and delimiters for each language.
for ext, l of languages
# Does the line begin with a comment?
l.comment_matcher = new RegExp('^\\s*' + l.symbol + '\\s?')
# Ignore [hashbangs](http://en.wikipedia.org/wiki/Shebang_(Unix\))
# and interpolations...
l.comment_filter = new RegExp('(^#![/]|^\\s*#\\{)')
# The dividing token we feed into Pygments, to delimit the boundaries between
# sections.
l.divider_text = '\n' + l.symbol + 'DIVIDER\n'
# The mirror of `divider_text` that we expect Pygments to return. We can split
# on this to recover the original sections.
# Note: the class is "c" for Python and "c1" for the other languages
l.divider_html = new RegExp('\\n*<span class="c1?">' + l.symbol + 'DIVIDER<\\/span>\\n*')
# Get the current language we're documenting, based on the extension.
get_language = (source) -> languages[path.extname(source)]
# Compute the destination HTML path for an input source file path. If the source
# is `lib/example.coffee`, the HTML will be at `docs/example.html`
destination = (filepath) ->
'docs/' + path.basename(filepath, path.extname(filepath)) + '.html'
# Ensure that the destination directory exists.
ensure_directory = (dir, callback) ->
exec "mkdir -p #{dir}", -> callback()
# Micro-templating, originally by John Resig, borrowed by way of
# [Underscore.js](http://documentcloud.github.com/underscore/).
template = (str) ->
new Function 'obj',
'var p=[],print=function(){p.push.apply(p,arguments);};' +
'with(obj){p.push(\'' +
str.replace(/[\r\t\n]/g, " ")
.replace(/'(?=[^<]*%>)/g,"\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(/<%=(.+?)%>/g, "',$1,'")
.split('<%').join("');")
.split('%>').join("p.push('") +
"');}return p.join('');"
# Create the template that we will use to generate the Docco HTML page.
docco_template = template fs.readFileSync(__dirname + '/../resources/docco.jst').toString()
# The CSS styles we'd like to apply to the documentation.
docco_styles = fs.readFileSync(__dirname + '/../resources/docco.css').toString()
# The start of each Pygments highlight block.
highlight_start = '<div class="highlight"><pre>'
# The end of each Pygments highlight block.
highlight_end = '</pre></div>'
# Run the script.
# For each source file passed in as an argument, generate the documentation.
sources = process.ARGV.sort()
if sources.length
ensure_directory 'docs', ->
fs.writeFile 'docs/docco.css', docco_styles
files = sources.slice(0)
next_file = -> generate_documentation files.shift(), next_file if files.length
next_file()

View File

@@ -23,7 +23,7 @@ module.exports = (grunt) ->
grunt.loadNpmTasks('grunt-contrib-coffee')
grunt.loadNpmTasks('grunt-contrib-less')
grunt.loadNpmTasks('grunt-shell')
grunt.loadNpmTasks('grunt-download-atom-shell')
grunt.loadNpmTasks('grunt-download-electron')
grunt.loadNpmTasks('grunt-electron-installer')
grunt.loadNpmTasks('grunt-peg')
grunt.loadTasks('tasks')
@@ -31,39 +31,52 @@ module.exports = (grunt) ->
# This allows all subsequent paths to the relative to the root of the repo
grunt.file.setBase(path.resolve('..'))
if not grunt.option('verbose')
grunt.log.writeln = (args...) -> grunt.log
grunt.log.write = (args...) -> grunt.log
[major, minor, patch] = packageJson.version.split('.')
tmpDir = os.tmpdir()
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
buildDir = path.resolve(buildDir)
# Options
installDir = grunt.option('install-dir')
buildDir = grunt.option('build-dir')
buildDir ?= path.join(os.tmpdir(), 'atom-build')
buildDir = path.resolve(buildDir)
disableAutoUpdate = grunt.option('no-auto-update') ? false
home = if process.platform is 'win32' then process.env.USERPROFILE else process.env.HOME
atomShellDownloadDir = path.join(home, '.atom', 'atom-shell')
channel = grunt.option('channel')
channel ?= process.env.JANKY_BRANCH if process.env.JANKY_BRANCH in ['stable', 'beta']
channel ?= 'dev'
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
metadata = packageJson
appName = packageJson.productName
appFileName = packageJson.name
apmFileName = 'apm'
if channel is 'beta'
appName += ' Beta'
appFileName += '-beta'
apmFileName += '-beta'
appName += '.app' if process.platform is 'darwin'
shellAppDir = path.join(buildDir, appName)
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
if process.platform is 'win32'
homeDir = process.env.USERPROFILE
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
installDir ?= path.join(process.env.ProgramFiles, appName)
killCommand = 'taskkill /F /IM atom.exe'
else if process.platform is 'darwin'
homeDir = process.env.HOME
contentsDir = path.join(shellAppDir, 'Contents')
appDir = path.join(contentsDir, 'Resources', 'app')
installDir ?= path.join('/Applications', appName)
killCommand = 'pkill -9 Atom'
else
homeDir = process.env.HOME
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
killCommand ='pkill -9 atom'
installDir = path.resolve(installDir)
electronDownloadDir = path.join(homeDir, '.atom', 'electron')
coffeeConfig =
glob_to_multiple:
@@ -100,13 +113,12 @@ module.exports = (grunt) ->
prebuildLessConfig =
src: [
'static/**/*.less'
'node_modules/atom-space-pen-views/stylesheets/**/*.less'
]
csonConfig =
options:
rootObject: true
cachePath: path.join(home, '.atom', 'compile-cache', 'grunt-cson')
cachePath: path.join(homeDir, '.atom', 'compile-cache', 'grunt-cson')
glob_to_multiple:
expand: true
@@ -157,7 +169,11 @@ module.exports = (grunt) ->
grunt.initConfig
pkg: grunt.file.readJSON('package.json')
atom: {appDir, appName, symbolsDir, buildDir, contentsDir, installDir, shellAppDir}
atom: {
appName, channel, metadata, disableAutoUpdate,
appFileName, apmFileName,
appDir, buildDir, contentsDir, installDir, shellAppDir, symbolsDir,
}
docsOutputDir: 'docs/output'
@@ -225,11 +241,11 @@ module.exports = (grunt) ->
'static/**/*.less'
]
'download-atom-shell':
version: packageJson.atomShellVersion
outputDir: 'atom-shell'
downloadDir: atomShellDownloadDir
rebuild: true # rebuild native modules after atom-shell is updated
'download-electron':
version: packageJson.electronVersion
outputDir: 'electron'
downloadDir: electronDownloadDir
rebuild: true # rebuild native modules after electron is updated
token: process.env.ATOM_ACCESS_TOKEN
'create-windows-installer':
@@ -238,8 +254,8 @@ module.exports = (grunt) ->
outputDirectory: path.join(buildDir, 'installer')
authors: 'GitHub 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', 'atom.ico')
iconUrl: "https://raw.githubusercontent.com/atom/atom/master/resources/app-icons/#{channel}/atom.ico"
setupIcon: path.resolve(__dirname, '..', 'resources', 'app-icons', channel, 'atom.ico')
remoteReleases: 'https://atom.io/api/updates'
shell:
@@ -254,7 +270,7 @@ module.exports = (grunt) ->
grunt.registerTask('lint', ['standard', 'coffeelint', 'csslint', 'lesslint'])
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
ciTasks = ['output-disk-space', 'download-atom-shell', 'download-atom-shell-chromedriver', 'build']
ciTasks = ['output-disk-space', 'download-electron', 'download-electron-chromedriver', 'build']
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar')
ciTasks.push('mkdeb') if process.platform is 'linux'
@@ -266,6 +282,7 @@ module.exports = (grunt) ->
ciTasks.push('publish-build') unless process.env.TRAVIS
grunt.registerTask('ci', ciTasks)
defaultTasks = ['download-atom-shell', 'download-atom-shell-chromedriver', 'build', 'set-version', 'generate-asar']
defaultTasks.push 'install' unless process.platform is 'linux'
defaultTasks = ['download-electron', 'download-electron-chromedriver', 'build', 'set-version', 'generate-asar']
unless process.platform is 'linux' or grunt.option('no-install')
defaultTasks.push 'install'
grunt.registerTask('default', defaultTasks)

View File

@@ -83,6 +83,10 @@
"hasDeprecations": true,
"latestHasDeprecations": false
},
"atom-eslint": {
"hasAlternative": true,
"alternative": "linter"
},
"atom-faker": {
"version": "<=0.2.0",
"hasDeprecations": true,
@@ -92,6 +96,10 @@
"hasAlternative": true,
"alternative": "linter"
},
"atom-go-format": {
"hasAlternative": true,
"alternative": "go-plus"
},
"atom-grunt-configs": {
"version": "<=0.1.0",
"hasDeprecations": true,
@@ -238,7 +246,7 @@
},
"autocomplete-jedi": {
"hasAlternative": true,
"alternative": "autocomplete-plus-python-jedi"
"alternative": "autocomplete-python"
},
"autocomplete-paths": {
"version": "<=1.0.1",
@@ -260,6 +268,10 @@
"hasDeprecations": true,
"latestHasDeprecations": true
},
"autocomplete-plus-python-jedi": {
"hasAlternative": true,
"alternative": "autocomplete-python"
},
"autocomplete-snippets": {
"version": "<=1.0.0",
"hasDeprecations": true,
@@ -702,9 +714,8 @@
"latestHasDeprecations": true
},
"highlight-css-color": {
"version": "<=1.3.0",
"hasDeprecations": true,
"latestHasDeprecations": true
"hasAlternative": true,
"alternative": "pigments"
},
"highlight-line": {
"version": "<=0.9.3",
@@ -996,9 +1007,8 @@
"latestHasDeprecations": true
},
"max-tabs": {
"version": "<=0.3.0",
"hasDeprecations": true,
"latestHasDeprecations": true
"hasAlternative": true,
"alternative": "tidy-tabs"
},
"maximize-panes": {
"version": "<=0.1.0",
@@ -1045,6 +1055,10 @@
"hasDeprecations": true,
"latestHasDeprecations": false
},
"nbsp-detect": {
"hasAlternative": true,
"alternative": "core"
},
"node-debugger": {
"version": "<=0.2.3",
"hasDeprecations": true,
@@ -1257,6 +1271,10 @@
"hasDeprecations": true,
"latestHasDeprecations": true
},
"remember-session": {
"hasAlternative": true,
"alternative": "core"
},
"remote-atom": {
"version": "<=1.2.0",
"hasDeprecations": true,
@@ -1500,6 +1518,10 @@
"hasDeprecations": true,
"latestHasDeprecations": false
},
"ternjs": {
"hasAlternative": true,
"alternative": "atom-ternjs"
},
"test-status": {
"version": "<=0.27.1",
"hasDeprecations": true,

View File

@@ -6,12 +6,12 @@
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"asar": "^0.5.0",
"asar": "^0.7.1",
"async": "~0.2.9",
"donna": "1.0.10",
"formidable": "~1.0.14",
"fs-plus": "2.x",
"github-releases": "~0.2.0",
"github-releases": "~0.3.0",
"glob": "^5.0.14",
"grunt": "~0.4.1",
"grunt-babel": "^5.0.1",
@@ -20,9 +20,9 @@
"grunt-contrib-coffee": "~0.12.0",
"grunt-contrib-csslint": "~0.2.0",
"grunt-contrib-less": "~0.8.0",
"grunt-cson": "0.14.0",
"grunt-download-atom-shell": "~0.15.1",
"grunt-electron-installer": "1.0.0",
"grunt-cson": "0.16.0",
"grunt-download-electron": "^2.1.1",
"grunt-electron-installer": "1.0.4",
"grunt-lesslint": "0.17.0",
"grunt-peg": "~1.1.0",
"grunt-shell": "~0.3.1",
@@ -33,7 +33,7 @@
"rcedit": "~0.3.0",
"request": "~2.27.0",
"rimraf": "~2.2.2",
"runas": "^2",
"runas": "^3.1",
"tello": "1.0.5",
"temp": "~0.8.1",
"underscore-plus": "1.x",

View File

@@ -15,9 +15,17 @@ module.exports = (grunt) ->
mkdir path.dirname(buildDir)
if process.platform is 'darwin'
cp 'atom-shell/Atom.app', shellAppDir, filter: /default_app/
cp 'electron/Electron.app', shellAppDir, filter: /default_app/
fs.renameSync path.join(shellAppDir, 'Contents', 'MacOS', 'Electron'), path.join(shellAppDir, 'Contents', 'MacOS', 'Atom')
fs.renameSync path.join(shellAppDir, 'Contents', 'Frameworks', 'Electron Helper.app'), path.join(shellAppDir, 'Contents', 'Frameworks', 'Atom Helper.app')
fs.renameSync path.join(shellAppDir, 'Contents', 'Frameworks', 'Atom Helper.app', 'Contents', 'MacOS', 'Electron Helper'), path.join(shellAppDir, 'Contents', 'Frameworks', 'Atom Helper.app', 'Contents', 'MacOS', 'Atom Helper')
else
cp 'atom-shell', shellAppDir, filter: /default_app/
cp 'electron', shellAppDir, filter: /default_app/
if process.platform is 'win32'
fs.renameSync path.join(shellAppDir, 'electron.exe'), path.join(shellAppDir, 'atom.exe')
else
fs.renameSync path.join(shellAppDir, 'electron'), path.join(shellAppDir, 'atom')
mkdir appDir
@@ -29,10 +37,8 @@ module.exports = (grunt) ->
packageNames = []
packageDirectories = []
nonPackageDirectories = [
'benchmark'
'dot-atom'
'vendor'
'resources'
]
{devDependencies} = grunt.file.readJSON('package.json')
@@ -78,19 +84,12 @@ module.exports = (grunt) ->
path.join('build', 'Release', 'obj')
path.join('build', 'Release', '.deps')
path.join('vendor', 'apm')
path.join('resources', 'linux')
path.join('resources', 'mac')
path.join('resources', 'win')
# These are only require in dev mode when the grammar isn't precompiled
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'
@@ -142,19 +141,14 @@ module.exports = (grunt) ->
testFolderPattern = new RegExp("#{_.escapeRegExp(path.sep)}_*te?sts?_*#{_.escapeRegExp(path.sep)}")
exampleFolderPattern = new RegExp("#{_.escapeRegExp(path.sep)}examples?#{_.escapeRegExp(path.sep)}")
benchmarkFolderPattern = new RegExp("#{_.escapeRegExp(path.sep)}benchmarks?#{_.escapeRegExp(path.sep)}")
nodeModulesFilter = new RegExp(ignoredPaths.join('|'))
filterNodeModule = (pathToCopy) ->
return true if benchmarkFolderPattern.test(pathToCopy)
pathToCopy = path.resolve(pathToCopy)
nodeModulesFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy)
packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(cson|coffee)$)")
filterPackage = (pathToCopy) ->
return true if benchmarkFolderPattern.test(pathToCopy)
pathToCopy = path.resolve(pathToCopy)
packageFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy)
@@ -171,10 +165,14 @@ module.exports = (grunt) ->
if process.platform isnt 'win32'
fs.symlinkSync(path.join('..', '..', 'bin', 'apm'), path.resolve(appDir, '..', 'new-app', 'apm', 'node_modules', '.bin', 'apm'))
channel = grunt.config.get('atom.channel')
cp path.join('resources', 'app-icons', channel, 'png', '1024.png'), path.join(appDir, 'resources', 'atom.png')
if process.platform is 'darwin'
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
unless /.+\.plist/.test(sourcePath)
grunt.file.copy(sourcePath, path.resolve(appDir, '..', subDirectory, filename))
cp path.join('resources', 'app-icons', channel, 'atom.icns'), path.resolve(appDir, '..', 'atom.icns')
cp path.join('resources', 'mac', 'file.icns'), path.resolve(appDir, '..', 'file.icns')
cp path.join('resources', 'mac', 'speakeasy.pem'), path.resolve(appDir, '..', 'speakeasy.pem')
if process.platform is 'win32'
cp path.join('resources', 'win', 'atom.cmd'), path.join(shellAppDir, 'resources', 'cli', 'atom.cmd')
@@ -183,9 +181,10 @@ module.exports = (grunt) ->
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')
cp path.join('resources', 'app-icons', channel, 'png'), 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'
dependencies.push('disable-autoupdate') if grunt.config.get('atom.disableAutoUpdate')
grunt.task.run(dependencies...)

View File

@@ -12,6 +12,7 @@ module.exports = (grunt) ->
rm require('../src/less-compile-cache').cacheDir
rm path.join(tmpdir, 'atom-cached-atom-shells')
rm 'atom-shell'
rm 'electron'
grunt.registerTask 'clean', 'Delete all the build files', ->
homeDir = process.env[if process.platform is 'win32' then 'USERPROFILE' else 'HOME']

View File

@@ -0,0 +1,12 @@
fs = require 'fs'
path = require 'path'
module.exports = (grunt) ->
grunt.registerTask 'disable-autoupdate', 'Set up disableAutoUpdate field in package.json file', ->
appDir = fs.realpathSync(grunt.config.get('atom.appDir'))
metadata = grunt.file.readJSON(path.join(appDir, 'package.json'))
metadata._disableAutoUpdate = grunt.config.get('atom.disableAutoUpdate')
grunt.file.write(path.join(appDir, 'package.json'), JSON.stringify(metadata))

View File

@@ -6,17 +6,12 @@ _ = require 'underscore-plus'
donna = require 'donna'
tello = require 'tello'
moduleBlacklist = [
'space-pen'
]
module.exports = (grunt) ->
getClassesToInclude = ->
modulesPath = path.resolve(__dirname, '..', '..', 'node_modules')
classes = {}
fs.traverseTreeSync modulesPath, (modulePath) ->
return false if modulePath.match(/node_modules/g).length > 1 # dont need the dependencies of the dependencies
return false if path.basename(modulePath) in moduleBlacklist
return true unless path.basename(modulePath) is 'package.json'
return true unless fs.isFileSync(modulePath)

View File

@@ -1,15 +1,19 @@
path = require 'path'
_ = require 'underscore-plus'
fs = require 'fs-plus'
runas = null
temp = require 'temp'
module.exports = (grunt) ->
{cp, mkdir, rm} = require('./task-helpers')(grunt)
{cp, fillTemplate, mkdir, rm} = require('./task-helpers')(grunt)
grunt.registerTask 'install', 'Install the built application', ->
appName = grunt.config.get('atom.appName')
appFileName = grunt.config.get('atom.appFileName')
apmFileName = grunt.config.get('atom.apmFileName')
buildDir = grunt.config.get('atom.buildDir')
installDir = grunt.config.get('atom.installDir')
shellAppDir = grunt.config.get('atom.shellAppDir')
{description} = grunt.config.get('atom.metadata')
if process.platform is 'win32'
runas ?= require 'runas'
@@ -18,7 +22,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, 'atom.exe'), 'Atom'])
runas('cmd', ['/c', createShortcut, path.join(installDir, 'atom.exe'), appName])
else if process.platform is 'darwin'
rm installDir
mkdir path.dirname(installDir)
@@ -28,32 +32,29 @@ module.exports = (grunt) ->
cp shellAppDir, tempFolder
fs.renameSync(tempFolder, installDir)
else
binDir = path.join(installDir, 'bin')
shareDir = path.join(installDir, 'share', 'atom')
mkdir binDir
cp 'atom.sh', path.join(binDir, 'atom')
shareDir = path.join(installDir, 'share', appFileName)
rm shareDir
mkdir path.dirname(shareDir)
cp shellAppDir, shareDir
# Create atom.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', 'atom.desktop.in')
desktopInstallFile = path.join(installDir, 'share', 'applications', 'atom.desktop')
unless installDir.indexOf(process.env.TMPDIR ? '/tmp') is 0
iconPath = path.join(shareDir, 'resources', 'app.asar.unpacked', 'resources', 'atom.png')
{description} = grunt.file.readJSON('package.json')
iconName = path.join(shareDir, 'resources', 'app.asar.unpacked', 'resources', 'atom.png')
executable = path.join(shareDir, 'atom')
template = _.template(String(fs.readFileSync(desktopFile)))
filled = template({description, iconName, executable})
mkdir path.join(installDir, 'share', 'applications')
fillTemplate(
path.join('resources', 'linux', 'atom.desktop.in'),
path.join(installDir, 'share', 'applications', appFileName + '.desktop'),
{appName, appFileName, description, iconPath, installDir}
)
grunt.file.write(desktopInstallFile, filled)
binDir = path.join(installDir, 'bin')
mkdir binDir
cp 'atom.sh', path.join(binDir, appFileName)
# Create relative symbol link for apm.
process.chdir(binDir)
rm('apm')
fs.symlinkSync(path.join('..', 'share', 'atom', 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'), 'apm')
rm(path.join(binDir, apmFileName))
fs.symlinkSync(
path.join('..', 'share', appFileName, 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'),
path.join(binDir, apmFileName)
)
fs.chmodSync(path.join(shareDir, 'atom'), "755")
fs.chmodSync(path.join(shareDir, 'atom'), '755')

View File

@@ -1,28 +1,19 @@
fs = require 'fs'
path = require 'path'
_ = require 'underscore-plus'
module.exports = (grunt) ->
{spawn} = require('./task-helpers')(grunt)
fillTemplate = (filePath, data) ->
template = _.template(String(fs.readFileSync("#{filePath}.in")))
filled = template(data)
outputPath = path.join(grunt.config.get('atom.buildDir'), path.basename(filePath))
grunt.file.write(outputPath, filled)
outputPath
getInstalledSize = (buildDir, callback) ->
cmd = 'du'
args = ['-sk', path.join(buildDir, 'Atom')]
spawn {cmd, args}, (error, {stdout}) ->
installedSize = stdout.split(/\s+/)?[0] or '200000' # default to 200MB
callback(null, installedSize)
{spawn, fillTemplate} = require('./task-helpers')(grunt)
grunt.registerTask 'mkdeb', 'Create debian package', ->
done = @async()
appName = grunt.config.get('atom.appName')
appFileName = grunt.config.get('atom.appFileName')
apmFileName = grunt.config.get('atom.apmFileName')
buildDir = grunt.config.get('atom.buildDir')
installDir = '/usr'
shellAppDir = grunt.config.get('atom.shellAppDir')
{version, description} = grunt.config.get('atom.metadata')
channel = grunt.config.get('atom.channel')
if process.arch is 'ia32'
arch = 'i386'
@@ -31,23 +22,38 @@ module.exports = (grunt) ->
else
return done("Unsupported arch #{process.arch}")
{name, version, description} = grunt.file.readJSON('package.json')
section = 'devel'
maintainer = 'GitHub <atom@github.com>'
installDir = '/usr'
iconName = 'atom'
executable = path.join(installDir, 'share', 'atom', 'atom')
getInstalledSize buildDir, (error, installedSize) ->
data = {name, version, description, section, arch, maintainer, installDir, iconName, installedSize, executable}
controlFilePath = fillTemplate(path.join('resources', 'linux', 'debian', 'control'), data)
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'atom.desktop'), data)
icon = path.join('resources', 'atom.png')
desktopFilePath = path.join(buildDir, appFileName + '.desktop')
fillTemplate(
path.join('resources', 'linux', 'atom.desktop.in'),
desktopFilePath,
{appName, appFileName, description, installDir, iconPath: appFileName}
)
getInstalledSize shellAppDir, (error, installedSize) ->
if error?
return done(error)
controlFilePath = path.join(buildDir, 'control')
fillTemplate(
path.join('resources', 'linux', 'debian', 'control.in'),
controlFilePath,
{appFileName, version, arch, installedSize, description}
)
iconPath = path.join(shellAppDir, 'resources', 'app.asar.unpacked', 'resources', 'atom.png')
cmd = path.join('script', 'mkdeb')
args = [version, arch, controlFilePath, desktopFilePath, icon, buildDir]
args = [appFileName, version, channel, arch, controlFilePath, desktopFilePath, iconPath, buildDir]
spawn {cmd, args}, (error) ->
if error?
done(error)
else
grunt.log.ok "Created #{buildDir}/atom-#{version}-#{arch}.deb"
grunt.log.ok "Created #{buildDir}/#{appFileName}-#{version}-#{arch}.deb"
done()
getInstalledSize = (directory, callback) ->
cmd = 'du'
args = ['-sk', directory]
spawn {cmd, args}, (error, {stdout}) ->
installedSize = stdout.split(/\s+/)?[0] or '200000' # default to 200MB
callback(null, installedSize)

View File

@@ -1,21 +1,18 @@
fs = require 'fs'
path = require 'path'
_ = require 'underscore-plus'
module.exports = (grunt) ->
{spawn, rm, mkdir} = require('./task-helpers')(grunt)
fillTemplate = (filePath, data) ->
template = _.template(String(fs.readFileSync("#{filePath}.in")))
filled = template(data)
outputPath = path.join(grunt.config.get('atom.buildDir'), path.basename(filePath))
grunt.file.write(outputPath, filled)
outputPath
{spawn, fillTemplate, rm, mkdir} = require('./task-helpers')(grunt)
grunt.registerTask 'mkrpm', 'Create rpm package', ->
done = @async()
appName = grunt.config.get('atom.appName')
appFileName = grunt.config.get('atom.appFileName')
apmFileName = grunt.config.get('atom.apmFileName')
buildDir = grunt.config.get('atom.buildDir')
installDir = '/usr'
{version, description} = grunt.config.get('atom.metadata')
if process.arch is 'ia32'
arch = 'i386'
else if process.arch is 'x64'
@@ -23,24 +20,32 @@ module.exports = (grunt) ->
else
return done("Unsupported arch #{process.arch}")
{name, version, description} = grunt.file.readJSON('package.json')
buildDir = grunt.config.get('atom.buildDir')
desktopFilePath = path.join(buildDir, appFileName + '.desktop')
fillTemplate(
path.join('resources', 'linux', 'atom.desktop.in'),
desktopFilePath,
{appName, appFileName, description, installDir, iconPath: appFileName}
)
# RPM versions can't have dashes in them.
# * http://www.rpm.org/max-rpm/ch-rpm-file-format.html
# * https://github.com/mojombo/semver/issues/145
version = version.replace(/-beta/, "~beta")
version = version.replace(/-dev/, "~dev")
specFilePath = path.join(buildDir, appFileName + '.spec')
fillTemplate(
path.join('resources', 'linux', 'redhat', 'atom.spec.in'),
specFilePath,
{appName, appFileName, apmFileName, installDir, version, description}
)
rpmDir = path.join(buildDir, 'rpm')
rm rpmDir
mkdir rpmDir
installDir = grunt.config.get('atom.installDir')
shareDir = path.join(installDir, 'share', 'atom')
iconName = 'atom'
executable = path.join(shareDir, 'atom')
data = {name, version, description, installDir, iconName, executable}
specFilePath = fillTemplate(path.join('resources', 'linux', 'redhat', 'atom.spec'), data)
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'atom.desktop'), data)
cmd = path.join('script', 'mkrpm')
args = [specFilePath, desktopFilePath, buildDir]
args = [appName, appFileName, specFilePath, desktopFilePath, buildDir]
spawn {cmd, args}, (error) ->
if error?
done(error)

View File

@@ -23,8 +23,6 @@ module.exports = (grunt) ->
importFallbackVariables = (lessFilePath) ->
if lessFilePath.indexOf('static') is 0
false
else if lessFilePath.indexOf('atom-space-pen-views') isnt -1
false
else
true

View File

@@ -22,7 +22,7 @@ module.exports = (gruntObject) ->
grunt.registerTask 'publish-build', 'Publish the built app', ->
tasks = []
tasks.push('build-docs', 'prepare-docs') if process.platform is 'darwin'
tasks.push('upload-assets') if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
tasks.push('upload-assets')
grunt.task.run(tasks)
grunt.registerTask 'prepare-docs', 'Move api.json to atom-api.json', ->
@@ -31,6 +31,15 @@ module.exports = (gruntObject) ->
cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json')
grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', ->
branchName = process.env.JANKY_BRANCH
switch branchName
when 'stable'
isPrerelease = false
when 'beta'
isPrerelease = true
else
return
doneCallback = @async()
startTime = Date.now()
done = (args...) ->
@@ -46,7 +55,7 @@ module.exports = (gruntObject) ->
zipAssets buildDir, assets, (error) ->
return done(error) if error?
getAtomDraftRelease (error, release) ->
getAtomDraftRelease isPrerelease, branchName, (error, release) ->
return done(error) if error?
assetNames = (asset.assetName for asset in assets)
deleteExistingAssets release, assetNames, (error) ->
@@ -68,7 +77,12 @@ getAssets = ->
]
when 'win32'
assets = [{assetName: 'atom-windows.zip', sourcePath: 'Atom'}]
for squirrelAsset in ['AtomSetup.exe', 'RELEASES', "atom-#{version}-full.nupkg", "atom-#{version}-delta.nupkg"]
# NuGet packages can't have dots in their pre-release name, so we remove
# those dots in `grunt-electron-installer` when generating the package.
nupkgVersion = version.replace(/\.(\d+)$/, '$1')
for squirrelAsset in ['AtomSetup.exe', 'RELEASES', "atom-#{nupkgVersion}-full.nupkg", "atom-#{nupkgVersion}-delta.nupkg"]
cp path.join(buildDir, 'installer', squirrelAsset), path.join(buildDir, squirrelAsset)
assets.push({assetName: squirrelAsset, sourcePath: assetName})
assets
@@ -120,9 +134,9 @@ zipAssets = (buildDir, assets, callback) ->
tasks.push(zip.bind(this, buildDir, sourcePath, assetName))
async.parallel(tasks, callback)
getAtomDraftRelease = (callback) ->
getAtomDraftRelease = (isPrerelease, branchName, callback) ->
atomRepo = new GitHub({repo: 'atom/atom', token})
atomRepo.getReleases (error, releases=[]) ->
atomRepo.getReleases {prerelease: isPrerelease}, (error, releases=[]) ->
if error?
logError('Fetching atom/atom releases failed', error, releases)
callback(error)
@@ -142,9 +156,9 @@ getAtomDraftRelease = (callback) ->
firstDraft.assets = assets
callback(null, firstDraft)
else
createAtomDraftRelease(callback)
createAtomDraftRelease(isPrerelease, branchName, callback)
createAtomDraftRelease = (callback) ->
createAtomDraftRelease = (isPrerelease, branchName, callback) ->
{version} = require('../../package.json')
options =
uri: 'https://api.github.com/repos/atom/atom/releases'
@@ -152,6 +166,8 @@ createAtomDraftRelease = (callback) ->
headers: defaultHeaders
json:
tag_name: "v#{version}"
prerelease: isPrerelease
target_commitish: branchName
name: version
draft: true
body: """

View File

@@ -4,9 +4,10 @@ module.exports = (grunt) ->
grunt.registerTask 'set-exe-icon', 'Set icon of the exe', ->
done = @async()
channel = grunt.config.get('atom.channel')
shellAppDir = grunt.config.get('atom.shellAppDir')
shellExePath = path.join(shellAppDir, 'atom.exe')
iconPath = path.resolve('resources', 'win', 'atom.ico')
iconPath = path.resolve('resources', 'app-icons', channel, 'atom.ico')
rcedit = require('rcedit')
rcedit(shellExePath, {'icon': iconPath}, done)

View File

@@ -5,7 +5,7 @@ module.exports = (grunt) ->
{spawn} = require('./task-helpers')(grunt)
getVersion = (callback) ->
onBuildMachine = process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
onBuildMachine = process.env.JANKY_SHA1 and process.env.JANKY_BRANCH in ['stable', 'beta']
inRepository = fs.existsSync(path.resolve(__dirname, '..', '..', '.git'))
{version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json'))
if onBuildMachine or not inRepository

View File

@@ -1,5 +1,6 @@
fs = require 'fs-plus'
path = require 'path'
_ = require 'underscore-plus'
module.exports = (grunt) ->
cp: (source, destination, {filter}={}) ->
@@ -66,3 +67,7 @@ module.exports = (grunt) ->
engines?.atom?
catch error
false
fillTemplate: (templatePath, outputPath, data) ->
content = _.template(String(fs.readFileSync(templatePath)))(data)
grunt.file.write(outputPath, content)

View File

@@ -17,7 +17,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
### Ubuntu / Debian
* `sudo apt-get install build-essential git libgnome-keyring-dev fakeroot`
* Instructions for [Node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions).
* Make sure the command `node` is available after Node.js installation (some systems install it as `nodejs`).
* Use `which node` to check if it is available.
* Use `sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10` to update it.
@@ -25,7 +25,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
### Fedora / CentOS / RHEL
* `sudo dnf --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools`
* Instructions for [Node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#fedora).
* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#enterprise-linux-and-fedora).
### Arch

View File

@@ -14,19 +14,21 @@
If it is installed elsewhere, you can create a symbolic link to the
directory containing the python.exe using:
`mklink /d %SystemDrive%\Python27 D:\elsewhere\Python27`
* [GitHub for Windows](http://windows.github.com/)
* [GitHub Desktop](http://desktop.github.com/)
### On Windows 8 or 10
* [Visual Studio Express 2013 or 2015 for Windows Desktop](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_2)
* For VS 2015, be sure to customize the installation to include Visual C++. It's not installed by default.
* Some have experienced issues with Node locating C++ on VS 2015. If so, try VS 2013.
* [node.js](http://nodejs.org/download/) (0.10.x or 0.12.x) or [io.js](https://iojs.org) (1.x or 2.x)
* [Python](https://www.python.org/downloads/) v2.7.x (required by [node-gyp](https://github.com/TooTallNate/node-gyp))
* [GitHub for Windows](http://windows.github.com/)
* [GitHub Desktop](http://desktop.github.com/)
## Instructions
```bash
# Use the `Git Shell` program which was installed by GitHub for Windows.
# Also make sure that you are logged into GitHub for Windows.
# Use the `Git Shell` program which was installed by GitHub Desktop.
# Also make sure that you are logged into GitHub Desktop.
cd C:\
git clone https://github.com/atom/atom/
cd atom
@@ -40,15 +42,14 @@ We will assume the git shell for these instructions.
* `--build-dir` - Build the application in this directory.
* `--verbose` - Verbose mode. A lot more information output.
## Why do I have to use GitHub for Windows?
## Why do I have to use GitHub Desktop?
You don't. You can use your existing Git! GitHub for Windows's Git Shell is just
easier to set up.
You don't. You can use your existing Git! GitHub Desktop's Git Shell is just easier to set up.
If you _prefer_ using your existing Git installation, make sure git's cmd directory is in your PATH env variable (e.g. `C:\Program Files (x86)\Git\cmd`) before you open your powershell or command window.
Note that you may have to open your command window as administrator. For powershell that doesn't seem to always be the case, though.
If none of this works, do install Github for Windows and use its Git shell. Makes life easier.
If none of this works, do install Github Desktop and use its Git shell. Makes life easier.
## Troubleshooting
@@ -59,7 +60,6 @@ If none of this works, do install Github for Windows and use its Git shell. Make
* If you just installed node, you'll need to restart your computer before node is
available on your Path.
* `script/build` outputs only the Node and Python versions before returning
* Try moving the repository to `C:\atom`. Most likely, the path is too long.
@@ -73,7 +73,7 @@ If none of this works, do install Github for Windows and use its Git shell. Make
* https://github.com/TooTallNate/node-gyp/issues/297
* https://code.google.com/p/gyp/issues/detail?id=393
* `script/build` stops at installing runas with 'Failed at the runas@0.5.4 install script.'
* `script/build` stops at installing runas with 'Failed at the runas@x.y.z install script.'
See the next item.

View File

@@ -2,7 +2,6 @@ TextBuffer = require 'text-buffer'
{Point, Range} = TextBuffer
{File, Directory} = require 'pathwatcher'
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
{includeDeprecatedAPIs, deprecate} = require 'grim'
module.exports =
BufferedNodeProcess: require '../src/buffered-node-process'
@@ -23,104 +22,3 @@ module.exports =
unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
module.exports.Task = require '../src/task'
module.exports.TextEditor = require '../src/text-editor'
if includeDeprecatedAPIs
{$, $$, $$$, View} = require '../src/space-pen-extensions'
Object.defineProperty module.exports, 'Workspace', get: ->
deprecate """
Requiring `Workspace` from `atom` is no longer supported.
If you need this, please open an issue on
https://github.com/atom/atom/issues/new
And let us know what you are using it for.
"""
require '../src/workspace'
Object.defineProperty module.exports, 'WorkspaceView', get: ->
deprecate """
Requiring `WorkspaceView` from `atom` is no longer supported.
Use `atom.views.getView(atom.workspace)` instead.
"""
require '../src/workspace-view'
Object.defineProperty module.exports, '$', get: ->
deprecate """
Requiring `$` from `atom` is no longer supported.
If you are using `space-pen`, please require `$` from `atom-space-pen-views`. Otherwise require `jquery` instead:
`{$} = require 'atom-space-pen-views'`
or
`$ = require 'jquery'`
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
Or add `"jquery": "^2"` to your package dependencies.
"""
$
Object.defineProperty module.exports, '$$', get: ->
deprecate """
Requiring `$$` from `atom` is no longer supported.
Please require `atom-space-pen-views` instead:
`{$$} = require 'atom-space-pen-views'`
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
$$
Object.defineProperty module.exports, '$$$', get: ->
deprecate """
Requiring `$$$` from `atom` is no longer supported.
Please require `atom-space-pen-views` instead:
`{$$$} = require 'atom-space-pen-views'`
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
$$$
Object.defineProperty module.exports, 'View', get: ->
deprecate """
Requiring `View` from `atom` is no longer supported.
Please require `atom-space-pen-views` instead:
`{View} = require 'atom-space-pen-views'`
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
View
Object.defineProperty module.exports, 'EditorView', get: ->
deprecate """
Requiring `EditorView` from `atom` is no longer supported.
Please require `TextEditorView` from `atom-space-pen-view` instead:
`{TextEditorView} = require 'atom-space-pen-views'`
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
require '../src/text-editor-view'
Object.defineProperty module.exports, 'TextEditorView', get: ->
deprecate """
Requiring `TextEditorView` from `atom` is no longer supported.
Please require `TextEditorView` from `atom-space-pen-view` instead:
`{TextEditorView} = require 'atom-space-pen-views'`
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
require '../src/text-editor-view'
Object.defineProperty module.exports, 'ScrollView', get: ->
deprecate """
Requiring `ScrollView` from `atom` is no longer supported.
Please require `ScrollView` from `atom-space-pen-view` instead:
`{ScrollView} = require 'atom-space-pen-views'`
Note that the API has changed slightly! Please read the docs at https://github.com/atom/atom-space-pen-views
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
require '../src/scroll-view'
Object.defineProperty module.exports, 'SelectListView', get: ->
deprecate """
Requiring `SelectListView` from `atom` is no longer supported.
Please require `SelectListView` from `atom-space-pen-view` instead:
`{SelectListView} = require 'atom-space-pen-views'`
Note that the API has changed slightly! Please read the docs at https://github.com/atom/atom-space-pen-views
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
"""
require '../src/select-list-view'
if includeDeprecatedAPIs
Object.defineProperty module.exports, 'Git', get: ->
deprecate "Please require `GitRepository` instead of `Git`: `{GitRepository} = require 'atom'`"
module.exports.GitRepository

View File

@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "1.0.12",
"version": "1.2.0-dev",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/browser/main.js",
"repository": {
@@ -12,52 +12,45 @@
"url": "https://github.com/atom/atom/issues"
},
"license": "MIT",
"atomShellVersion": "0.22.3",
"electronVersion": "0.30.7",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "^5.1.10",
"atom-space-pen-views": "^2.1.0",
"atom-keymap": "^6.0.0",
"babel-core": "^5.8.21",
"bootstrap": "^3.3.4",
"clear-cut": "^2.0.1",
"coffee-script": "1.8.0",
"color": "^0.7.3",
"delegato": "^1",
"emissary": "^1.3.3",
"event-kit": "^1.3.0",
"first-mate": "^5.0.0",
"fs-plus": "^2.8.0",
"fstream": "0.1.24",
"fuzzaldrin": "^2.1",
"git-utils": "^3.0.0",
"git-utils": "^4",
"grim": "1.4.2",
"jasmine-json": "~0.0",
"jasmine-tagged": "^1.1.4",
"jquery": "^2.1.1",
"key-path-helpers": "^0.3.0",
"less-cache": "0.22",
"marked": "^0.3.4",
"mixto": "^1",
"normalize-package-data": "^2.0.0",
"nslog": "^2.0.0",
"oniguruma": "^4.1",
"pathwatcher": "^4.4.3",
"nslog": "^3",
"oniguruma": "^5",
"pathwatcher": "^6.2",
"property-accessors": "^1.1.3",
"q": "^1.1.2",
"random-words": "0.0.1",
"runas": "2.0.0",
"scandal": "2.1.2",
"runas": "^3.1",
"scandal": "^2.2",
"scoped-property-store": "^0.17.0",
"scrollbar-style": "^3.1",
"scrollbar-style": "^3.2",
"season": "^5.3",
"semver": "^4.3.3",
"serializable": "^1",
"service-hub": "^0.6.2",
"source-map-support": "^0.3.2",
"space-pen": "3.8.2",
"stacktrace-parser": "0.1.1",
"temp": "0.8.1",
"text-buffer": "6.7.1",
"theorist": "^1.0.2",
"text-buffer": "7.1.2",
"typescript-simple": "1.0.0",
"underscore-plus": "^1.6.6",
"yargs": "^3.23.0"
@@ -67,85 +60,85 @@
"atom-dark-ui": "0.51.0",
"atom-light-syntax": "0.28.0",
"atom-light-ui": "0.43.0",
"base16-tomorrow-dark-theme": "0.27.0",
"base16-tomorrow-light-theme": "0.9.0",
"one-dark-ui": "1.0.3",
"one-dark-syntax": "1.1.0",
"one-light-syntax": "1.1.0",
"one-light-ui": "1.0.3",
"base16-tomorrow-dark-theme": "1.0.0",
"base16-tomorrow-light-theme": "1.0.0",
"one-dark-ui": "1.1.5",
"one-dark-syntax": "1.1.1",
"one-light-syntax": "1.1.1",
"one-light-ui": "1.1.5",
"solarized-dark-syntax": "0.38.1",
"solarized-light-syntax": "0.22.1",
"about": "1.1.0",
"archive-view": "0.60.0",
"archive-view": "0.61.0",
"autocomplete-atom-api": "0.9.2",
"autocomplete-css": "0.10.1",
"autocomplete-css": "0.11.0",
"autocomplete-html": "0.7.2",
"autocomplete-plus": "2.19.0",
"autocomplete-plus": "2.21.0",
"autocomplete-snippets": "1.7.1",
"autoflow": "0.25.0",
"autosave": "0.22.0",
"background-tips": "0.26.0",
"bookmarks": "0.36.0",
"bracket-matcher": "0.76.0",
"bookmarks": "0.38.0",
"bracket-matcher": "0.78.0",
"command-palette": "0.36.0",
"deprecation-cop": "0.54.0",
"dev-live-reload": "0.46.0",
"dev-live-reload": "0.47.0",
"encoding-selector": "0.21.0",
"exception-reporting": "0.36.0",
"find-and-replace": "0.180.0",
"fuzzy-finder": "0.88.0",
"git-diff": "0.55.0",
"exception-reporting": "0.37.0",
"find-and-replace": "0.185.0",
"fuzzy-finder": "0.90.0",
"git-diff": "0.56.0",
"go-to-line": "0.30.0",
"grammar-selector": "0.47.0",
"image-view": "0.54.0",
"incompatible-packages": "0.24.1",
"image-view": "0.55.0",
"incompatible-packages": "0.25.0",
"keybinding-resolver": "0.33.0",
"line-ending-selector": "0.0.5",
"link": "0.30.0",
"markdown-preview": "0.150.0",
"metrics": "0.51.0",
"link": "0.31.0",
"markdown-preview": "0.154.0",
"metrics": "0.52.0",
"notifications": "0.59.0",
"open-on-github": "0.38.0",
"package-generator": "0.40.0",
"release-notes": "0.53.0",
"settings-view": "0.216.0",
"snippets": "0.95.0",
"spell-check": "0.59.0",
"settings-view": "0.224.0",
"snippets": "0.100.0",
"spell-check": "0.61.0",
"status-bar": "0.79.0",
"styleguide": "0.44.0",
"symbols-view": "0.104.0",
"symbols-view": "0.109.0",
"tabs": "0.84.0",
"timecop": "0.31.0",
"tree-view": "0.186.0",
"timecop": "0.33.0",
"tree-view": "0.189.0",
"update-package-dependencies": "0.10.0",
"welcome": "0.30.0",
"whitespace": "0.31.0",
"wrap-guide": "0.36.0",
"language-c": "0.47.1",
"language-clojure": "0.16.0",
"language-coffee-script": "0.41.0",
"language-csharp": "0.8.0",
"wrap-guide": "0.38.0",
"language-c": "0.48.0",
"language-clojure": "0.17.0",
"language-coffee-script": "0.42.0",
"language-csharp": "0.10.0",
"language-css": "0.34.0",
"language-gfm": "0.81.0",
"language-git": "0.10.0",
"language-go": "0.37.0",
"language-html": "0.41.2",
"language-go": "0.39.0",
"language-html": "0.41.3",
"language-hyperlink": "0.14.0",
"language-java": "0.16.0",
"language-javascript": "0.93.0",
"language-json": "0.16.0",
"language-javascript": "0.96.0",
"language-json": "0.17.0",
"language-less": "0.28.2",
"language-make": "0.17.0",
"language-mustache": "0.12.0",
"language-make": "0.18.0",
"language-mustache": "0.13.0",
"language-objective-c": "0.15.0",
"language-perl": "0.28.0",
"language-php": "0.29.0",
"language-perl": "0.29.0",
"language-php": "0.30.0",
"language-property-list": "0.8.0",
"language-python": "0.40.0",
"language-ruby": "0.57.0",
"language-ruby-on-rails": "0.22.0",
"language-ruby": "0.60.0",
"language-ruby-on-rails": "0.23.0",
"language-sass": "0.41.0",
"language-shellscript": "0.16.0",
"language-shellscript": "0.17.0",
"language-source": "0.9.0",
"language-sql": "0.17.0",
"language-text": "0.7.0",

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 182 KiB

View File

Before

Width:  |  Height:  |  Size: 628 KiB

After

Width:  |  Height:  |  Size: 628 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 944 B

After

Width:  |  Height:  |  Size: 944 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 KiB

View File

@@ -1,9 +1,9 @@
[Desktop Entry]
Name=Atom
Name=<%= appName %>
Comment=<%= description %>
GenericName=Text Editor
Exec=<%= executable %> %U
Icon=<%= iconName %>
Exec=<%= installDir %>/share/<%= appFileName %>/atom %U
Icon=<%= iconPath %>
Type=Application
StartupNotify=true
Categories=GNOME;GTK;Utility;TextEditor;Development;

View File

@@ -1,12 +1,12 @@
Package: <%= name %>
Package: <%= appFileName %>
Version: <%= version %>
Depends: git, gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11 | libgcrypt20, libnotify4, libxtst6, libnss3, python, gvfs-bin, xdg-utils, libcap2
Recommends: lsb-release
Suggests: libgnome-keyring0, gir1.2-gnomekeyring-1.0
Section: <%= section %>
Section: devel
Priority: optional
Architecture: <%= arch %>
Installed-Size: <%= installedSize %>
Maintainer: <%= maintainer %>
Maintainer: GitHub <atom@github.com>
Description: <%= description %>
Atom is a free and open source text editor that is modern, approachable, and hackable to the core.

View File

@@ -1,4 +1,4 @@
Name: <%= name %>
Name: <%= appFileName %>
Version: <%= version %>
Release: 0.1%{?dist}
Summary: <%= description %>
@@ -13,25 +13,23 @@ Requires: lsb-core-noarch
<%= description %>
%install
mkdir -p %{buildroot}/<%= installDir %>/share/atom/
cp -r Atom/* %{buildroot}/<%= installDir %>/share/atom/
mkdir -p %{buildroot}/<%= installDir %>/bin/
ln -sf ../share/atom/resources/app/apm/node_modules/.bin/apm %{buildroot}/<%= installDir %>/bin/apm
cp atom.sh %{buildroot}/<%= installDir %>/bin/atom
chmod 755 %{buildroot}/<%= installDir %>/bin/atom
mkdir -p %{buildroot}/<%= installDir %>/share/applications/
cp atom.desktop %{buildroot}/<%= installDir %>/share/applications/
mkdir -p "%{buildroot}/<%= installDir %>/share/<%= appFileName %>/"
cp -r "<%= appName %>"/* "%{buildroot}/<%= installDir %>/share/<%= appFileName %>/"
mkdir -p "%{buildroot}/<%= installDir %>/bin/"
ln -sf "../share/<%= appFileName %>/resources/app/apm/node_modules/.bin/apm" "%{buildroot}/<%= installDir %>/bin/<%= apmFileName %>"
cp atom.sh "%{buildroot}/<%= installDir %>/bin/<%= appFileName %>"
chmod 755 "%{buildroot}/<%= installDir %>/bin/<%= appFileName %>"
mkdir -p "%{buildroot}/<%= installDir %>/share/applications/"
cp "<%= appFileName %>.desktop" "%{buildroot}/<%= installDir %>/share/applications/"
# copy over icons in sizes that most desktop environments like
for i in 1024 512 256 128 64 48 32 24 16
do
mkdir -p %{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps
cp icons/${i}.png %{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps/atom.png
for i in 1024 512 256 128 64 48 32 24 16; do
mkdir -p "%{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps"
cp "icons/${i}.png" "%{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps/<%= appFileName %>.png"
done
%files
<%= installDir %>/bin/atom
<%= installDir %>/bin/apm
<%= installDir %>/share/atom/
<%= installDir %>/share/applications/atom.desktop
<%= installDir %>/bin/<%= appFileName %>
<%= installDir %>/bin/<%= apmFileName %>
<%= installDir %>/share/<%= appFileName %>/
<%= installDir %>/share/applications/<%= appFileName %>.desktop
<%= installDir %>/share/icons/hicolor/

View File

@@ -62,6 +62,8 @@ function bootstrap() {
'temp'
];
process.env.ATOM_RESOURCE_PATH = path.resolve(__dirname, '..');
var buildInstallCommand = initialNpmCommand + npmFlags + 'install';
var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')};
var apmInstallCommand = npmPath + npmFlags + '--target=0.10.35 ' + 'install';

View File

@@ -22,11 +22,16 @@ function loadEnvironmentVariables(filePath) {
}
function readEnvironmentVariables() {
if (process.platform === 'win32')
if (process.platform === 'win32') {
loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials'));
else if (process.platform === 'darwin') {
} else if (process.platform === 'darwin') {
loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials');
loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain');
} else if (process.platform === 'linux') {
// Use Clang for building native code, the GCC on Precise is too old.
process.env.CC = 'clang';
process.env.CXX = 'clang++';
process.env.npm_config_clang = '1';
}
}

View File

@@ -20,12 +20,14 @@ var commands = [
[__dirname, '..', 'build', 'node_modules'],
[__dirname, '..', 'apm', 'node_modules'],
[__dirname, '..', 'atom-shell'],
[__dirname, '..', 'electron'],
[home, '.atom', '.node-gyp'],
[home, '.atom', 'storage'],
[home, '.atom', '.apm'],
[home, '.atom', '.npm'],
[home, '.atom', 'compile-cache'],
[home, '.atom', 'atom-shell'],
[home, '.atom', 'electron'],
[tmpdir, 'atom-build'],
[tmpdir, 'atom-cached-atom-shells'],
];

View File

@@ -1,5 +1,5 @@
#!/bin/bash
# mkdeb version control-file-path deb-file-path
# mkdeb name version channel arch control-file-path desktop-file-path icon-path deb-file-path
set -e
@@ -7,20 +7,22 @@ SCRIPT=`readlink -f "$0"`
ROOT=`readlink -f $(dirname $SCRIPT)/..`
cd $ROOT
VERSION="$1"
ARCH="$2"
CONTROL_FILE="$3"
DESKTOP_FILE="$4"
ICON_FILE="$5"
DEB_PATH="$6"
NAME="$1"
VERSION="$2"
CHANNEL="$3"
ARCH="$4"
CONTROL_FILE="$5"
DESKTOP_FILE="$6"
ICON_FILE="$7"
DEB_PATH="$8"
FILE_MODE=755
TARGET_ROOT="`mktemp -d`"
chmod $FILE_MODE "$TARGET_ROOT"
TARGET="$TARGET_ROOT/atom-$VERSION-$ARCH"
TARGET="$TARGET_ROOT/$NAME-$VERSION-$ARCH"
mkdir -m $FILE_MODE -p "$TARGET/usr"
env INSTALL_PREFIX="$TARGET/usr" script/grunt install
env INSTALL_PREFIX="$TARGET/usr" script/grunt install --channel $CHANNEL
mkdir -m $FILE_MODE -p "$TARGET/DEBIAN"
cp "$CONTROL_FILE" "$TARGET/DEBIAN/control"
@@ -29,19 +31,19 @@ mkdir -m $FILE_MODE -p "$TARGET/usr/share/applications"
cp "$DESKTOP_FILE" "$TARGET/usr/share/applications"
mkdir -m $FILE_MODE -p "$TARGET/usr/share/pixmaps"
cp "$ICON_FILE" "$TARGET/usr/share/pixmaps"
cp "$ICON_FILE" "$TARGET/usr/share/pixmaps/$NAME.png"
# Copy generated LICENSE.md to /usr/share/doc/atom/copyright
mkdir -m $FILE_MODE -p "$TARGET/usr/share/doc/atom"
cp "$TARGET/usr/share/atom/resources/LICENSE.md" "$TARGET/usr/share/doc/atom/copyright"
mkdir -m $FILE_MODE -p "$TARGET/usr/share/doc/$NAME"
cp "$TARGET/usr/share/$NAME/resources/LICENSE.md" "$TARGET/usr/share/doc/$NAME/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/atom"
cp "$ROOT/resources/linux/debian/lintian-overrides" "$TARGET/usr/share/lintian/overrides/$NAME"
# Remove executable bit from .node files
find "$TARGET" -type f -name "*.node" -exec chmod a-x {} \;
fakeroot dpkg-deb -b "$TARGET"
mv "$TARGET_ROOT/atom-$VERSION-$ARCH.deb" "$DEB_PATH"
mv "$TARGET_ROOT/$NAME-$VERSION-$ARCH.deb" "$DEB_PATH"
rm -rf "$TARGET_ROOT"

View File

@@ -2,22 +2,24 @@
set -e
SPEC_FILE="$1"
DESKTOP_FILE="$2"
BUILD_DIRECTORY="$3"
APP_NAME="$1"
APP_FILE_NAME="$2"
SPEC_FILE="$3"
DESKTOP_FILE="$4"
BUILD_DIRECTORY="$5"
RPM_BUILD_ROOT=~/rpmbuild
ARCH=`uname -m`
rpmdev-setuptree
cp -r $BUILD_DIRECTORY/Atom $RPM_BUILD_ROOT/BUILD
cp -r $BUILD_DIRECTORY/icons $RPM_BUILD_ROOT/BUILD
cp $SPEC_FILE $RPM_BUILD_ROOT/SPECS
cp ./atom.sh $RPM_BUILD_ROOT/BUILD
cp $DESKTOP_FILE $RPM_BUILD_ROOT/BUILD
cp -r "$BUILD_DIRECTORY/$APP_NAME" "$RPM_BUILD_ROOT/BUILD"
cp -r "$BUILD_DIRECTORY/icons" "$RPM_BUILD_ROOT/BUILD"
cp "$SPEC_FILE" "$RPM_BUILD_ROOT/SPECS"
cp ./atom.sh "$RPM_BUILD_ROOT/BUILD"
cp "$DESKTOP_FILE" "$RPM_BUILD_ROOT/BUILD"
rpmbuild -ba $SPEC_FILE
cp $RPM_BUILD_ROOT/RPMS/$ARCH/atom-*.rpm $BUILD_DIRECTORY/rpm
rpmbuild -ba "$SPEC_FILE"
cp $RPM_BUILD_ROOT/RPMS/$ARCH/$APP_FILE_NAME-*.rpm "$BUILD_DIRECTORY/rpm"
rm -rf $RPM_BUILD_ROOT
rm -rf "$RPM_BUILD_ROOT"

89
script/railcar Executable file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/env node
var fs = require('fs')
var exec = require('child_process').exec
var series = require('async').series
var semver = require('semver')
series([
section('Preparing to roll the railcars'),
checkCleanWorkingTree,
run('git fetch origin master:master beta:beta stable:stable'),
run('git fetch origin --tags'),
section('Updating stable branch'),
run('git checkout stable'),
run('git merge --ff-only origin/stable'),
run('git merge --ff-only origin/beta'),
bumpStableVersion,
section('Updating beta branch'),
run('git checkout beta'),
run('git merge --ff-only origin/beta'),
run('git merge --ff-only origin/master'),
run('git merge --strategy ours origin/stable'),
bumpBetaVersion,
section('Updating master branch'),
run('git checkout master'),
run('git merge --ff-only origin/master'),
run('git merge --strategy ours origin/beta'),
bumpDevVersion,
section('Pushing changes upstream'),
run('git push origin master:master beta:beta stable:stable'),
run('git push origin --tags')
], finish)
function checkCleanWorkingTree (next) {
run('git status --porcelain')(function (error, output) {
if (error) return next(error)
if (output.trim().length > 0) return next(new Error('Cannot run the railcars with a dirty working tree'))
next()
})
}
function bumpStableVersion (next) {
run('npm version patch')(next)
}
function bumpBetaVersion (next) {
var newVersion = semver.inc(getCurrentVersion(), 'preminor', 'beta')
run('npm version ' + newVersion)(next)
}
function bumpDevVersion (next) {
var newVersion = semver.inc(getCurrentVersion(), 'preminor', 'dev').replace(/\.0$/, '')
series([
run('npm --no-git-tag-version version ' + newVersion),
run('git commit -am "' + newVersion + '"')
], next)
}
function finish (error) {
if (error) {
console.log('Error: ' + error.message)
process.exit(1)
}
console.log('OK, now just wait for all CI builds to pass on beta and stable')
}
function getCurrentVersion () {
return JSON.parse(fs.readFileSync(require.resolve('../package.json'))).version
}
function run (command) {
return function (next) {
console.log('>', command)
exec(command, next)
}
}
function section (message) {
return function (next) {
console.log()
console.log(message)
next()
}
}

View File

@@ -1,15 +1,9 @@
{$} = require '../src/space-pen-extensions'
describe '"atom" protocol URL', ->
it 'sends the file relative in the package as response', ->
called = false
callback = -> called = true
$.ajax
url: 'atom://async/package.json'
success: callback
# In old versions of jQuery, ajax calls to custom protocol would always
# be treated as error eventhough the browser thinks it's a success
# request.
error: callback
request = new XMLHttpRequest()
request.addEventListener('load', -> called = true)
request.open('GET', 'atom://async/package.json', true)
request.send()
waitsFor 'request to be done', -> called is true

View File

@@ -1,9 +1,10 @@
path = require 'path'
_ = require 'underscore-plus'
{View, $, $$} = require '../src/space-pen-extensions'
grim = require 'grim'
marked = require 'marked'
listen = require '../src/delegated-listener'
formatStackTrace = (spec, message='', stackTrace) ->
return stackTrace unless stackTrace
@@ -30,30 +31,43 @@ formatStackTrace = (spec, message='', stackTrace) ->
lines.join('\n').trim()
module.exports =
class AtomReporter extends View
@content: ->
@div class: 'spec-reporter', =>
@div class: 'padded pull-right', =>
@button outlet: 'reloadButton', class: 'btn btn-small reload-button', 'Reload Specs'
@div outlet: 'coreArea', class: 'symbol-area', =>
@div outlet: 'coreHeader', class: 'symbol-header'
@ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
@div outlet: 'bundledArea', class: 'symbol-area', =>
@div outlet: 'bundledHeader', class: 'symbol-header'
@ul outlet: 'bundledSummary', class: 'symbol-summary list-unstyled'
@div outlet: 'userArea', class: 'symbol-area', =>
@div outlet: 'userHeader', class: 'symbol-header'
@ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
@div outlet: "status", class: 'status alert alert-info', =>
@div outlet: "time", class: 'time'
@div outlet: "specCount", class: 'spec-count'
@div outlet: "message", class: 'message'
@div outlet: "results", class: 'results'
class AtomReporter
@div outlet: "deprecations", class: 'status alert alert-warning', style: 'display: none', =>
@span outlet: 'deprecationStatus', '0 deprecations'
@div class: 'deprecation-toggle'
@div outlet: 'deprecationList', class: 'deprecation-list'
constructor: ->
@element = document.createElement('div')
@element.innerHTML = """
<div class="spec-reporter">
<div class="padded pull-right">
<button outlet="reloadButton" class="btn btn-small reload-button">Reload Specs</button>
</div>
<div outlet="coreArea" class="symbol-area">
<div outlet="coreHeader" class="symbol-header"></div>
<ul outlet="coreSummary"class="symbol-summary list-unstyled"></ul>
</div>
<div outlet="bundledArea" class="symbol-area">
<div outlet="bundledHeader" class="symbol-header"></div>
<ul outlet="bundledSummary"class="symbol-summary list-unstyled"></ul>
</div>
<div outlet="userArea" class="symbol-area">
<div outlet="userHeader" class="symbol-header"></div>
<ul outlet="userSummary"class="symbol-summary list-unstyled"></ul>
</div>
<div outlet="status" class="status alert alert-info">
<div outlet="time" class="time"></div>
<div outlet="specCount" class="spec-count"></div>
<div outlet="message" class="message"></div>
</div>
<div outlet="results" class="results"></div>
<div outlet="deprecations" class="status alert alert-warning" style="display: none">
<span outlet="deprecationStatus">0 deprecations</span>
<div class="deprecation-toggle"></div>
</div>
<div outlet="deprecationList" class="deprecation-list"></div>
</div>
"""
for element in @element.querySelectorAll('[outlet]')
this[element.getAttribute('outlet')] = element
startedAt: null
runningSpecCount: 0
@@ -71,20 +85,18 @@ class AtomReporter extends View
specs = runner.specs()
@totalSpecCount = specs.length
@addSpecs(specs)
$(document.body).append this
@on 'click', '.stack-trace', ->
$(this).toggleClass('expanded')
@reloadButton.on 'click', -> require('ipc').send('call-window-method', 'restart')
document.body.appendChild(@element)
reportRunnerResults: (runner) ->
@updateSpecCounts()
@status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
if @failedCount is 0
@status.classList.add('alert-success')
@status.classList.remove('alert-info')
if @failedCount is 1
@message.text "#{@failedCount} failure"
@message.textContent = "#{@failedCount} failure"
else
@message.text "#{@failedCount} failures"
@message.textConent = "#{@failedCount} failures"
reportSuiteResults: (suite) ->
@@ -100,170 +112,214 @@ class AtomReporter extends View
addDeprecations: (spec) ->
deprecations = grim.getDeprecations()
@deprecationCount += deprecations.length
@deprecations.show() if @deprecationCount > 0
@deprecations.style.display = '' if @deprecationCount > 0
if @deprecationCount is 1
@deprecationStatus.text("1 deprecation")
@deprecationStatus.textContent = "1 deprecation"
else
@deprecationStatus.text("#{@deprecationCount} deprecations")
@deprecationStatus.textContent = "#{@deprecationCount} deprecations"
for deprecation in deprecations
@deprecationList.append $$ ->
@div class: 'padded', =>
@div class: 'result-message fail deprecation-message', =>
@raw marked(deprecation.message)
@deprecationList.appendChild(@buildDeprecationElement(spec, deprecation))
for stack in deprecation.getStacks()
fullStack = stack.map ({functionName, location}) ->
if functionName is '<unknown>'
" at #{location}"
else
" at #{functionName} (#{location})"
@pre class: 'stack-trace padded', formatStackTrace(spec, deprecation.message, fullStack.join('\n'))
grim.clearDeprecations()
handleEvents: ->
$(document).on "click", ".spec-toggle", ({currentTarget}) ->
element = $(currentTarget)
specFailures = element.parent().find('.spec-failures')
specFailures.toggle()
element.toggleClass('folded')
false
buildDeprecationElement: (spec, deprecation) ->
div = document.createElement('div')
div.className = 'padded'
div.innerHTML = """
<div class="result-message fail deprecation-message">
#{marked(deprecation.message)}
</div>
"""
$(document).on "click", ".deprecation-toggle", ({currentTarget}) ->
element = $(currentTarget)
deprecationList = $(document).find('.deprecation-list')
deprecationList.toggle()
element.toggleClass('folded')
false
for stack in deprecation.getStacks()
fullStack = stack.map ({functionName, location}) ->
if functionName is '<unknown>'
" at #{location}"
else
" at #{functionName} (#{location})"
pre = document.createElement('pre')
pre.className = 'stack-trace padded'
pre.textContent = formatStackTrace(spec, deprecation.message, fullStack.join('\n'))
div.appendChild(pre)
div
handleEvents: ->
listen document, 'click', '.spec-toggle', (event) ->
specFailures = event.currentTarget.parentElement.querySelector('.spec-failures')
if specFailures.style.display is 'none'
specFailures.style.display = ''
event.currentTarget.classList.remove('folded')
else
specFailures.style.display = 'none'
event.currentTarget.classList.add('folded')
event.preventDefault()
listen document, 'click', '.deprecation-list', (event) ->
deprecationList = event.currentTarget.parentElement.querySelector('.deprecation-list')
if deprecationList.style.display is 'none'
deprecationList.style.display = ''
event.currentTarget.classList.remove('folded')
else
deprecationList.style.display = 'none'
event.currentTarget.classList.add('folded')
event.preventDefault()
listen document, 'click', '.stack-trace', (event) ->
event.currentTarget.classList.toggle('expanded')
@reloadButton.addEventListener('click', -> require('ipc').send('call-window-method', 'restart'))
updateSpecCounts: ->
if @skippedCount
specCount = "#{@completeSpecCount - @skippedCount}/#{@totalSpecCount - @skippedCount} (#{@skippedCount} skipped)"
else
specCount = "#{@completeSpecCount}/#{@totalSpecCount}"
@specCount[0].textContent = specCount
@specCount.textContent = specCount
updateStatusView: (spec) ->
if @failedCount > 0
@status.addClass('alert-danger').removeClass('alert-info')
@status.classList.add('alert-danger')
@status.classList.remove('alert-info')
@updateSpecCounts()
rootSuite = spec.suite
rootSuite = rootSuite.parentSuite while rootSuite.parentSuite
@message.text rootSuite.description
@message.textContent = rootSuite.description
time = "#{Math.round((spec.endedAt - @startedAt) / 10)}"
time = "0#{time}" if time.length < 3
@time[0].textContent = "#{time[0...-2]}.#{time[-2..]}s"
@time.textContent = "#{time[0...-2]}.#{time[-2..]}s"
addSpecs: (specs) ->
coreSpecs = 0
bundledPackageSpecs = 0
userPackageSpecs = 0
for spec in specs
symbol = $$ -> @li id: "spec-summary-#{spec.id}", class: "spec-summary pending"
symbol = document.createElement('li')
symbol.setAttribute('id', "spec-summary-#{spec.id}")
symbol.className = "spec-summary pending"
switch spec.specType
when 'core'
coreSpecs++
@coreSummary.append symbol
@coreSummary.appendChild symbol
when 'bundled'
bundledPackageSpecs++
@bundledSummary.append symbol
@bundledSummary.appendChild symbol
when 'user'
userPackageSpecs++
@userSummary.append symbol
@userSummary.appendChild symbol
if coreSpecs > 0
@coreHeader.text("Core Specs (#{coreSpecs})")
@coreHeader.textContent = "Core Specs (#{coreSpecs})"
else
@coreArea.hide()
@coreArea.style.display = 'none'
if bundledPackageSpecs > 0
@bundledHeader.text("Bundled Package Specs (#{bundledPackageSpecs})")
@bundledHeader.textContent = "Bundled Package Specs (#{bundledPackageSpecs})"
else
@bundledArea.hide()
@bundledArea.style.display = 'none'
if userPackageSpecs > 0
if coreSpecs is 0 and bundledPackageSpecs is 0
# Package specs being run, show a more descriptive label
{specDirectory} = specs[0]
packageFolderName = path.basename(path.dirname(specDirectory))
packageName = _.undasherize(_.uncamelcase(packageFolderName))
@userHeader.text("#{packageName} Specs")
@userHeader.textContent = "#{packageName} Specs"
else
@userHeader.text("User Package Specs (#{userPackageSpecs})")
@userHeader.textContent = "User Package Specs (#{userPackageSpecs})"
else
@userArea.hide()
@userArea.style.display = 'none'
specStarted: (spec) ->
@runningSpecCount++
specComplete: (spec) ->
specSummaryElement = $("#spec-summary-#{spec.id}")
specSummaryElement.removeClass('pending')
specSummaryElement.setTooltip(title: spec.getFullName(), container: '.spec-reporter')
specSummaryElement = document.getElementById("spec-summary-#{spec.id}")
specSummaryElement.classList.remove('pending')
results = spec.results()
if results.skipped
specSummaryElement.addClass("skipped")
specSummaryElement.classList.add("skipped")
@skippedCount++
else if results.passed()
specSummaryElement.addClass("passed")
specSummaryElement.classList.add("passed")
@passedCount++
else
specSummaryElement.addClass("failed")
specSummaryElement.classList.add("failed")
specView = new SpecResultView(spec)
specView.attach()
@failedCount++
@addDeprecations(spec)
class SuiteResultView extends View
@content: ->
@div class: 'suite', =>
@div outlet: 'description', class: 'description'
initialize: (@suite) ->
@attr('id', "suite-view-#{@suite.id}")
@description.text(@suite.description)
class SuiteResultView
constructor: (@suite) ->
@element = document.createElement('div')
@element.className = 'suite'
@element.setAttribute('id', "suite-view-#{@suite.id}")
@description = document.createElement('div')
@description.className = 'description'
@description.textContent = @suite.description
@element.appendChild(@description)
attach: ->
(@parentSuiteView() or $('.results')).append this
(@parentSuiteView() or document.querySelector('.results')).appendChild(@element)
parentSuiteView: ->
return unless @suite.parentSuite
if not suiteView = $("#suite-view-#{@suite.parentSuite.id}").view()
unless suiteViewElement = document.querySelector("#suite-view-#{@suite.parentSuite.id}")
suiteView = new SuiteResultView(@suite.parentSuite)
suiteView.attach()
suiteViewElement = suiteView.element
suiteView
suiteViewElement
class SpecResultView extends View
@content: ->
@div class: 'spec', =>
@div class: 'spec-toggle'
@div outlet: 'description', class: 'description'
@div outlet: 'specFailures', class: 'spec-failures'
class SpecResultView
constructor: (@spec) ->
@element = document.createElement('div')
@element.className = 'spec'
@element.innerHTML = """
<div class='spec-toggle'></div>
<div outlet='description' class='description'></div>
<div outlet='specFailures' class='spec-failures'></div>
"""
@description = @element.querySelector('[outlet="description"]')
@specFailures = @element.querySelector('[outlet="specFailures"]')
initialize: (@spec) ->
@addClass("spec-view-#{@spec.id}")
@element.classList.add("spec-view-#{@spec.id}")
description = @spec.description
description = "it #{description}" if description.indexOf('it ') isnt 0
@description.text(description)
@description.textContent = description
for result in @spec.results().getItems() when not result.passed()
stackTrace = formatStackTrace(@spec, result.message, result.trace.stack)
@specFailures.append $$ ->
@div result.message, class: 'result-message fail'
@pre stackTrace, class: 'stack-trace padded' if stackTrace
resultElement = document.createElement('div')
resultElement.className = 'result-message fail'
resultElement.textContent = result.message
@specFailures.appendChild(resultElement)
if stackTrace
traceElement = document.createElement('pre')
traceElement.className = 'stack-trace padded'
traceElement.textContent = stackTrace
@specFailures.appendChild(traceElement)
attach: ->
@parentSuiteView().append this
@parentSuiteView().appendChild(@element)
parentSuiteView: ->
if not suiteView = $("#suite-view-#{@spec.suite.id}").view()
unless suiteViewElement = document.querySelector("#suite-view-#{@spec.suite.id}")
suiteView = new SuiteResultView(@spec.suite)
suiteView.attach()
suiteViewElement = suiteView.element
suiteView
suiteViewElement

View File

@@ -1,4 +1,3 @@
{$, $$} = require '../src/space-pen-extensions'
Exec = require('child_process').exec
path = require 'path'
Package = require '../src/package'
@@ -223,3 +222,31 @@ describe "the `atom` global", ->
spyOn(atom, "pickFolder").andCallFake (callback) -> callback(null)
atom.addProjectFolder()
expect(atom.project.getPaths()).toEqual(initialPaths)
describe "::unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", ->
workspaceState = atom.workspace.serialize()
syntaxState = atom.grammars.serialize()
projectState = atom.project.serialize()
atom.unloadEditorWindow()
expect(atom.state.workspace).toEqual workspaceState
expect(atom.state.grammars).toEqual syntaxState
expect(atom.state.project).toEqual projectState
expect(atom.saveSync).toHaveBeenCalled()
describe "::removeEditorWindow()", ->
it "unsubscribes from all buffers", ->
waitsForPromise ->
atom.workspace.open("sample.js")
runs ->
buffer = atom.workspace.getActivePaneItem().buffer
pane = atom.workspace.getActivePane()
pane.splitRight(copyActiveItem: true)
expect(atom.workspace.getTextEditors().length).toBe 2
atom.removeEditorWindow()
expect(buffer.getSubscriptionCount()).toBe 0

View File

@@ -1,34 +1,81 @@
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
installer = require '../src/command-installer'
CommandInstaller = require '../src/command-installer'
describe "install(commandPath, callback)", ->
commandFilePath = temp.openSync("atom-command").path
commandName = path.basename(commandFilePath)
installationPath = temp.mkdirSync("atom-bin")
installationFilePath = path.join(installationPath, commandName)
describe "CommandInstaller on #darwin", ->
[installer, resourcesPath, installationPath, atomBinPath, apmBinPath] = []
beforeEach ->
fs.chmodSync(commandFilePath, '755')
spyOn(installer, 'getInstallDirectory').andReturn installationPath
installationPath = temp.mkdirSync("atom-bin")
describe "on #darwin", ->
it "symlinks the command and makes it executable", ->
expect(fs.isFileSync(commandFilePath)).toBeTruthy()
expect(fs.isFileSync(installationFilePath)).toBeFalsy()
resourcesPath = temp.mkdirSync('atom-app')
atomBinPath = path.join(resourcesPath, 'app', 'atom.sh')
apmBinPath = path.join(resourcesPath, 'app', 'apm', 'node_modules', '.bin', 'apm')
fs.writeFileSync(atomBinPath, "")
fs.writeFileSync(apmBinPath, "")
fs.chmodSync(atomBinPath, '755')
fs.chmodSync(apmBinPath, '755')
installDone = false
installError = null
installer.createSymlink commandFilePath, false, (error) ->
installDone = true
installError = error
spyOn(CommandInstaller::, 'getResourcesDirectory').andReturn(resourcesPath)
spyOn(CommandInstaller::, 'getInstallDirectory').andReturn(installationPath)
waitsFor ->
installDone
describe "when using a stable version of atom", ->
beforeEach ->
installer = new CommandInstaller("2.0.2")
it "symlinks the atom command as 'atom'", ->
installedAtomPath = path.join(installationPath, 'atom')
expect(fs.isFileSync(installedAtomPath)).toBeFalsy()
waitsFor (done) ->
installer.installAtomCommand(false, done)
runs ->
expect(installError).toBeNull()
expect(fs.isFileSync(installationFilePath)).toBeTruthy()
expect(fs.realpathSync(installationFilePath)).toBe fs.realpathSync(commandFilePath)
expect(fs.isExecutableSync(installationFilePath)).toBeTruthy()
expect(fs.realpathSync(installedAtomPath)).toBe fs.realpathSync(atomBinPath)
expect(fs.isExecutableSync(installedAtomPath)).toBe true
expect(fs.isFileSync(path.join(installationPath, 'atom-beta'))).toBe false
it "symlinks the apm command as 'apm'", ->
installedApmPath = path.join(installationPath, 'apm')
expect(fs.isFileSync(installedApmPath)).toBeFalsy()
waitsFor (done) ->
installer.installApmCommand(false, done)
runs ->
expect(fs.realpathSync(installedApmPath)).toBe fs.realpathSync(apmBinPath)
expect(fs.isExecutableSync(installedApmPath)).toBeTruthy()
expect(fs.isFileSync(path.join(installationPath, 'apm-beta'))).toBe false
describe "when using a beta version of atom", ->
beforeEach ->
installer = new CommandInstaller("2.2.0-beta.0")
it "symlinks the atom command as 'atom-beta'", ->
installedAtomPath = path.join(installationPath, 'atom-beta')
expect(fs.isFileSync(installedAtomPath)).toBeFalsy()
waitsFor (done) ->
installer.installAtomCommand(false, done)
runs ->
expect(fs.realpathSync(installedAtomPath)).toBe fs.realpathSync(atomBinPath)
expect(fs.isExecutableSync(installedAtomPath)).toBe true
expect(fs.isFileSync(path.join(installationPath, 'atom'))).toBe false
it "symlinks the apm command as 'apm-beta'", ->
installedApmPath = path.join(installationPath, 'apm-beta')
expect(fs.isFileSync(installedApmPath)).toBeFalsy()
waitsFor (done) ->
installer.installApmCommand(false, done)
runs ->
expect(fs.realpathSync(installedApmPath)).toBe fs.realpathSync(apmBinPath)
expect(fs.isExecutableSync(installedApmPath)).toBeTruthy()
expect(fs.isFileSync(path.join(installationPath, 'apm'))).toBe false

View File

@@ -115,6 +115,15 @@ describe "CommandRegistry", ->
grandchild.dispatchEvent(dispatchedEvent)
expect(dispatchedEvent.abortKeyBinding).toHaveBeenCalled()
it "copies non-standard properties from the original event to the synthetic event", ->
syntheticEvent = null
registry.add '.child', 'command', (event) -> syntheticEvent = event
dispatchedEvent = new CustomEvent('command', bubbles: true)
dispatchedEvent.nonStandardProperty = 'testing'
grandchild.dispatchEvent(dispatchedEvent)
expect(syntheticEvent.nonStandardProperty).toBe 'testing'
it "allows listeners to be removed via a disposable returned by ::add", ->
calls = []

View File

@@ -2,7 +2,6 @@ path = require 'path'
temp = require 'temp'
CSON = require 'season'
fs = require 'fs-plus'
Grim = require 'grim'
describe "Config", ->
dotAtomPath = null
@@ -364,16 +363,6 @@ describe "Config", ->
expect(atom.config.save).not.toHaveBeenCalled()
expect(atom.config.get('foo.bar.baz', scope: ['.source.coffee'])).toBe 55
it "deprecates passing a scope selector as the first argument", ->
atom.config.setDefaults("foo", bar: baz: 10)
atom.config.set('foo.bar.baz', 55, scopeSelector: '.source.coffee')
spyOn(Grim, 'deprecate')
atom.config.unset('.source.coffee', 'foo.bar.baz')
expect(Grim.deprecate).toHaveBeenCalled()
expect(atom.config.get('foo.bar.baz', scope: ['.source.coffee'])).toBe 10
describe ".onDidChange(keyPath, {scope})", ->
[observeHandler, observeSubscription] = []
@@ -458,15 +447,6 @@ describe "Config", ->
expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: undefined})
changeSpy.reset()
it 'deprecates using a scope descriptor as an optional first argument', ->
keyPath = "foo.bar.baz"
spyOn(Grim, 'deprecate')
atom.config.onDidChange [".source.coffee", ".string.quoted.double.coffee"], keyPath, changeSpy = jasmine.createSpy()
expect(Grim.deprecate).toHaveBeenCalled()
atom.config.set("foo.bar.baz", 12)
expect(changeSpy).toHaveBeenCalledWith({oldValue: undefined, newValue: 12})
describe ".observe(keyPath, {scope})", ->
[observeHandler, observeSubscription] = []
@@ -535,16 +515,6 @@ describe "Config", ->
expect(observeHandler).toHaveBeenCalledWith("value 2")
expect(otherHandler).not.toHaveBeenCalledWith("value 2")
it "deprecates using a scope descriptor as the first argument", ->
spyOn(Grim, 'deprecate')
atom.config.observe([".some.scope"], "foo.bar.baz", observeHandler)
atom.config.observe([".another.scope"], "foo.bar.baz", otherHandler)
expect(Grim.deprecate).toHaveBeenCalled()
atom.config.set('foo.bar.baz', "value 2", scopeSelector: ".some")
expect(observeHandler).toHaveBeenCalledWith("value 2")
expect(otherHandler).not.toHaveBeenCalledWith("value 2")
it 'calls the callback when properties with more specific selectors are removed', ->
changeSpy = jasmine.createSpy()
atom.config.observe("foo.bar.baz", scope: [".source.coffee", ".string.quoted.double.coffee"], changeSpy)
@@ -1058,10 +1028,6 @@ describe "Config", ->
atom.config.setDefaults("foo.bar.baz", a: 2)
expect(updatedCallback.callCount).toBe 1
it "sets a default when the setting's key contains an escaped dot", ->
atom.config.setDefaults("foo", 'a\\.b': 1, b: 2)
expect(atom.config.get("foo")).toEqual 'a\\.b': 1, b: 2
describe ".setSchema(keyPath, schema)", ->
it 'creates a properly nested schema', ->
schema =
@@ -1629,135 +1595,3 @@ describe "Config", ->
expect(atom.config.set('foo.bar.arr', ['two', 'three'])).toBe true
expect(atom.config.get('foo.bar.arr')).toEqual ['two', 'three']
describe "Deprecated Methods", ->
describe ".getDefault(keyPath)", ->
it "returns a clone of the default value", ->
atom.config.setDefaults("foo", same: 1, changes: 1)
spyOn(Grim, 'deprecate')
expect(atom.config.getDefault('foo.same')).toBe 1
expect(atom.config.getDefault('foo.changes')).toBe 1
expect(Grim.deprecate.callCount).toBe 2
atom.config.set('foo.same', 2)
atom.config.set('foo.changes', 3)
expect(atom.config.getDefault('foo.same')).toBe 1
expect(atom.config.getDefault('foo.changes')).toBe 1
expect(Grim.deprecate.callCount).toBe 4
initialDefaultValue = [1, 2, 3]
atom.config.setDefaults("foo", bar: initialDefaultValue)
expect(atom.config.getDefault('foo.bar')).toEqual initialDefaultValue
expect(atom.config.getDefault('foo.bar')).not.toBe initialDefaultValue
expect(Grim.deprecate.callCount).toBe 6
describe "when scoped settings are used", ->
it "returns the global default when no scoped default set", ->
atom.config.setDefaults("foo", bar: baz: 10)
spyOn(Grim, 'deprecate')
expect(atom.config.getDefault('.source.coffee', 'foo.bar.baz')).toBe 10
expect(Grim.deprecate).toHaveBeenCalled()
it "returns the scoped settings not including the user's config file", ->
atom.config.setDefaults("foo", bar: baz: 10)
atom.config.set("foo.bar.baz", 42, scopeSelector: ".source.coffee", source: "some-source")
spyOn(Grim, 'deprecate')
expect(atom.config.getDefault('.source.coffee', 'foo.bar.baz')).toBe 42
expect(Grim.deprecate.callCount).toBe 1
atom.config.set('foo.bar.baz', 55, scopeSelector: '.source.coffee')
expect(atom.config.getDefault('.source.coffee', 'foo.bar.baz')).toBe 42
expect(Grim.deprecate.callCount).toBe 2
describe ".isDefault(keyPath)", ->
it "returns true when the value of the key path is its default value", ->
atom.config.setDefaults("foo", same: 1, changes: 1)
spyOn(Grim, 'deprecate')
expect(atom.config.isDefault('foo.same')).toBe true
expect(atom.config.isDefault('foo.changes')).toBe true
expect(Grim.deprecate.callCount).toBe 2
atom.config.set('foo.same', 2)
atom.config.set('foo.changes', 3)
expect(atom.config.isDefault('foo.same')).toBe false
expect(atom.config.isDefault('foo.changes')).toBe false
expect(Grim.deprecate.callCount).toBe 4
describe "when scoped settings are used", ->
it "returns false when a scoped setting was set by the user", ->
spyOn(Grim, 'deprecate')
expect(atom.config.isDefault('.source.coffee', 'foo.bar.baz')).toBe true
expect(Grim.deprecate.callCount).toBe 1
atom.config.set("foo.bar.baz", 42, scopeSelector: ".source.coffee", source: "something-else")
expect(atom.config.isDefault('.source.coffee', 'foo.bar.baz')).toBe true
expect(Grim.deprecate.callCount).toBe 2
atom.config.set('foo.bar.baz', 55, scopeSelector: '.source.coffee')
expect(atom.config.isDefault('.source.coffee', 'foo.bar.baz')).toBe false
expect(Grim.deprecate.callCount).toBe 3
describe ".toggle(keyPath)", ->
beforeEach ->
jasmine.snapshotDeprecations()
afterEach ->
jasmine.restoreDeprecationsSnapshot()
it "negates the boolean value of the current key path value", ->
atom.config.set('foo.a', 1)
atom.config.toggle('foo.a')
expect(atom.config.get('foo.a')).toBe false
atom.config.set('foo.a', '')
atom.config.toggle('foo.a')
expect(atom.config.get('foo.a')).toBe true
atom.config.set('foo.a', null)
atom.config.toggle('foo.a')
expect(atom.config.get('foo.a')).toBe true
atom.config.set('foo.a', true)
atom.config.toggle('foo.a')
expect(atom.config.get('foo.a')).toBe false
describe ".getSettings()", ->
it "returns all settings including defaults", ->
atom.config.setDefaults("foo", bar: baz: 10)
atom.config.set("foo.ok", 12)
jasmine.snapshotDeprecations()
expect(atom.config.getSettings().foo).toEqual
ok: 12
bar:
baz: 10
jasmine.restoreDeprecationsSnapshot()
describe ".getPositiveInt(keyPath, defaultValue)", ->
beforeEach ->
jasmine.snapshotDeprecations()
afterEach ->
jasmine.restoreDeprecationsSnapshot()
it "returns the proper coerced value", ->
atom.config.set('editor.preferredLineLength', 0)
expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 1
it "returns the proper coerced value", ->
atom.config.set('editor.preferredLineLength', -1234)
expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 1
it "returns the default value when a string is passed in", ->
atom.config.set('editor.preferredLineLength', 'abcd')
expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
it "returns the default value when null is passed in", ->
atom.config.set('editor.preferredLineLength', null)
expect(atom.config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80

View File

@@ -1,5 +1,3 @@
{$$} = require '../src/space-pen-extensions'
ContextMenuManager = require '../src/context-menu-manager'
describe "ContextMenuManager", ->
@@ -158,32 +156,3 @@ describe "ContextMenuManager", ->
catch error
addError = error
expect(addError.message).toContain('<>')
describe "when the menus are specified in a legacy format", ->
beforeEach ->
jasmine.snapshotDeprecations()
afterEach ->
jasmine.restoreDeprecationsSnapshot()
it "allows items to be specified in the legacy format for now", ->
contextMenu.add '.parent':
'A': 'a'
'Separator 1': '-'
'B':
'C': 'c'
'Separator 2': '-'
'D': 'd'
expect(contextMenu.templateForElement(parent)).toEqual [
{label: 'A', command: 'a'}
{type: 'separator'}
{
label: 'B'
submenu: [
{label: 'C', command: 'c'}
{type: 'separator'}
{label: 'D', command: 'd'}
]
}
]

View File

@@ -47,14 +47,6 @@ describe "DisplayBuffer", ->
buffer.insert([0, 0], oneHundredLines)
expect(displayBuffer.getLineCount()).toBe 100 + originalLineCount
it "reassigns the scrollTop if it exceeds the max possible value after lines are removed", ->
displayBuffer.setHeight(50)
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setScrollTop(80)
buffer.delete([[8, 0], [10, 0]])
expect(displayBuffer.getScrollTop()).toBe 60
it "updates the display buffer prior to invoking change handlers registered on the buffer", ->
buffer.onDidChange -> expect(displayBuffer2.tokenizedLineForScreenRow(0).text).toBe "testing"
displayBuffer2 = new DisplayBuffer({buffer, tabLength})
@@ -240,7 +232,8 @@ describe "DisplayBuffer", ->
describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", ->
it "correctly renders the original wrapped line", ->
buffer = atom.project.buildBufferSync(null, '')
displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, softWrapped: true})
displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30})
displayBuffer.setSoftWrapped(true)
buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.")
buffer.insert([0, Infinity], '\n')
@@ -281,6 +274,9 @@ describe "DisplayBuffer", ->
describe ".setEditorWidthInChars(length)", ->
it "changes the length at which lines are wrapped and emits a change event for all screen lines", ->
tokensText = (tokens) ->
_.pluck(tokens, 'value').join('')
displayBuffer.setEditorWidthInChars(40)
expect(tokensText displayBuffer.tokenizedLineForScreenRow(4).tokens).toBe ' left = [], right = [];'
expect(tokensText displayBuffer.tokenizedLineForScreenRow(5).tokens).toBe ' while(items.length > 0) {'
@@ -293,18 +289,6 @@ describe "DisplayBuffer", ->
displayBuffer.setEditorWidthInChars(-1)
expect(displayBuffer.editorWidthInChars).not.toBe -1
it "sets ::scrollLeft to 0 and keeps it there when soft wrapping is enabled", ->
displayBuffer.setDefaultCharWidth(10)
displayBuffer.setWidth(85)
displayBuffer.setSoftWrapped(false)
displayBuffer.setScrollLeft(Infinity)
expect(displayBuffer.getScrollLeft()).toBeGreaterThan 0
displayBuffer.setSoftWrapped(true)
expect(displayBuffer.getScrollLeft()).toBe 0
displayBuffer.setScrollLeft(10)
expect(displayBuffer.getScrollLeft()).toBe 0
describe "primitive folding", ->
beforeEach ->
displayBuffer.destroy()
@@ -734,21 +718,6 @@ describe "DisplayBuffer", ->
expect(displayBuffer.clipScreenPosition([0, 1], clip: 'forward')).toEqual [0, tabLength]
expect(displayBuffer.clipScreenPosition([0, tabLength], clip: 'forward')).toEqual [0, tabLength]
describe "::screenPositionForPixelPosition(pixelPosition)", ->
it "clips pixel positions above buffer start", ->
displayBuffer.setLineHeightInPixels(20)
expect(displayBuffer.screenPositionForPixelPosition(top: -Infinity, left: -Infinity)).toEqual [0, 0]
expect(displayBuffer.screenPositionForPixelPosition(top: -Infinity, left: Infinity)).toEqual [0, 0]
expect(displayBuffer.screenPositionForPixelPosition(top: -1, left: Infinity)).toEqual [0, 0]
expect(displayBuffer.screenPositionForPixelPosition(top: 0, left: Infinity)).toEqual [0, 29]
it "clips pixel positions below buffer end", ->
displayBuffer.setLineHeightInPixels(20)
expect(displayBuffer.screenPositionForPixelPosition(top: Infinity, left: -Infinity)).toEqual [12, 2]
expect(displayBuffer.screenPositionForPixelPosition(top: Infinity, left: Infinity)).toEqual [12, 2]
expect(displayBuffer.screenPositionForPixelPosition(top: displayBuffer.getHeight() + 1, left: 0)).toEqual [12, 2]
expect(displayBuffer.screenPositionForPixelPosition(top: displayBuffer.getHeight() - 1, left: 0)).toEqual [12, 0]
describe "::screenPositionForBufferPosition(bufferPosition, options)", ->
it "clips the specified buffer position", ->
expect(displayBuffer.screenPositionForBufferPosition([0, 2])).toEqual [0, 2]
@@ -1182,20 +1151,6 @@ describe "DisplayBuffer", ->
expect(marker1.getProperties()).toEqual a: 1, b: 2
expect(marker2.getProperties()).toEqual a: 1, b: 3
describe "Marker::getPixelRange()", ->
it "returns the start and end positions of the marker based on the line height and character widths assigned to the DisplayBuffer", ->
marker = displayBuffer.markScreenRange([[5, 10], [6, 4]])
displayBuffer.setLineHeightInPixels(20)
displayBuffer.setDefaultCharWidth(10)
for char in ['r', 'e', 't', 'u', 'r', 'n']
displayBuffer.setScopedCharWidth(["source.js", "keyword.control.js"], char, 11)
{start, end} = marker.getPixelRange()
expect(start.top).toBe 5 * 20
expect(start.left).toBe (4 * 10) + (6 * 11)
describe 'when there are multiple DisplayBuffers for a buffer', ->
describe 'when a marker is created', ->
it 'the second display buffer will not emit a marker-created event when the marker has been deleted in the first marker-created event', ->
@@ -1250,157 +1205,18 @@ describe "DisplayBuffer", ->
expect(displayBuffer.getDecorations(class: 'two').length).toEqual 0
expect(displayBuffer.getDecorations(class: 'one').length).toEqual 1
describe "::setScrollTop", ->
beforeEach ->
displayBuffer.setLineHeightInPixels(10)
it "disallows negative values", ->
displayBuffer.setHeight(displayBuffer.getScrollHeight() + 100)
expect(displayBuffer.setScrollTop(-10)).toBe 0
expect(displayBuffer.getScrollTop()).toBe 0
it "disallows values that would make ::getScrollBottom() exceed ::getScrollHeight()", ->
displayBuffer.setHeight(50)
maxScrollTop = displayBuffer.getScrollHeight() - displayBuffer.getHeight()
expect(displayBuffer.setScrollTop(maxScrollTop)).toBe maxScrollTop
expect(displayBuffer.getScrollTop()).toBe maxScrollTop
expect(displayBuffer.setScrollTop(maxScrollTop + 50)).toBe maxScrollTop
expect(displayBuffer.getScrollTop()).toBe maxScrollTop
describe "editor.scrollPastEnd", ->
describe "when editor.scrollPastEnd is false", ->
beforeEach ->
atom.config.set("editor.scrollPastEnd", false)
displayBuffer.setLineHeightInPixels(10)
it "does not add the height of the view to the scroll height", ->
lineHeight = displayBuffer.getLineHeightInPixels()
originalScrollHeight = displayBuffer.getScrollHeight()
displayBuffer.setHeight(50)
expect(displayBuffer.getScrollHeight()).toBe originalScrollHeight
describe "when editor.scrollPastEnd is true", ->
beforeEach ->
atom.config.set("editor.scrollPastEnd", true)
displayBuffer.setLineHeightInPixels(10)
it "adds the height of the view to the scroll height", ->
lineHeight = displayBuffer.getLineHeightInPixels()
originalScrollHeight = displayBuffer.getScrollHeight()
displayBuffer.setHeight(50)
expect(displayBuffer.getScrollHeight()).toEqual(originalScrollHeight + displayBuffer.height - (lineHeight * 3))
describe "::setScrollLeft", ->
beforeEach ->
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setDefaultCharWidth(10)
it "disallows negative values", ->
displayBuffer.setWidth(displayBuffer.getScrollWidth() + 100)
expect(displayBuffer.setScrollLeft(-10)).toBe 0
expect(displayBuffer.getScrollLeft()).toBe 0
it "disallows values that would make ::getScrollRight() exceed ::getScrollWidth()", ->
displayBuffer.setWidth(50)
maxScrollLeft = displayBuffer.getScrollWidth() - displayBuffer.getWidth()
expect(displayBuffer.setScrollLeft(maxScrollLeft)).toBe maxScrollLeft
expect(displayBuffer.getScrollLeft()).toBe maxScrollLeft
expect(displayBuffer.setScrollLeft(maxScrollLeft + 50)).toBe maxScrollLeft
expect(displayBuffer.getScrollLeft()).toBe maxScrollLeft
describe "::scrollToScreenPosition(position, [options])", ->
beforeEach ->
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setDefaultCharWidth(10)
displayBuffer.setHorizontalScrollbarHeight(0)
displayBuffer.setHeight(50)
displayBuffer.setWidth(150)
it "sets the scroll top and scroll left so the given screen position is in view", ->
displayBuffer.scrollToScreenPosition([8, 20])
expect(displayBuffer.getScrollBottom()).toBe (9 + displayBuffer.getVerticalScrollMargin()) * 10
expect(displayBuffer.getScrollRight()).toBe (20 + displayBuffer.getHorizontalScrollMargin()) * 10
it "triggers ::onDidRequestAutoscroll with the logical coordinates along with the options", ->
scrollSpy = jasmine.createSpy("::onDidRequestAutoscroll")
displayBuffer.onDidRequestAutoscroll(scrollSpy)
displayBuffer.scrollToScreenPosition([8, 20])
expect(displayBuffer.getScrollBottom()).toBe (9 + displayBuffer.getVerticalScrollMargin()) * 10
expect(displayBuffer.getScrollRight()).toBe (20 + displayBuffer.getHorizontalScrollMargin()) * 10
displayBuffer.scrollToScreenPosition([8, 20], center: true)
displayBuffer.scrollToScreenPosition([8, 20], center: false, reversed: true)
describe "when the 'center' option is true", ->
it "vertically scrolls to center the given position vertically", ->
displayBuffer.scrollToScreenPosition([8, 20], center: true)
expect(displayBuffer.getScrollTop()).toBe (8 * 10) + 5 - (50 / 2)
expect(displayBuffer.getScrollRight()).toBe (20 + displayBuffer.getHorizontalScrollMargin()) * 10
it "does not scroll vertically if the position is already in view", ->
displayBuffer.scrollToScreenPosition([4, 20], center: true)
expect(displayBuffer.getScrollTop()).toBe 0
describe "scroll width", ->
cursorWidth = 1
beforeEach ->
displayBuffer.setDefaultCharWidth(10)
it "recomputes the scroll width when the default character width changes", ->
expect(displayBuffer.getScrollWidth()).toBe 10 * 65 + cursorWidth
displayBuffer.setDefaultCharWidth(12)
expect(displayBuffer.getScrollWidth()).toBe 12 * 65 + cursorWidth
it "recomputes the scroll width when the max line length changes", ->
buffer.insert([6, 12], ' ')
expect(displayBuffer.getScrollWidth()).toBe 10 * 66 + cursorWidth
buffer.delete([[6, 10], [6, 12]], ' ')
expect(displayBuffer.getScrollWidth()).toBe 10 * 64 + cursorWidth
it "recomputes the scroll width when the scoped character widths change", ->
operatorWidth = 20
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth)
expect(displayBuffer.getScrollWidth()).toBe 10 * 64 + operatorWidth + cursorWidth
it "recomputes the scroll width when the scoped character widths change in a batch", ->
operatorWidth = 20
displayBuffer.onDidChangeCharacterWidths changedSpy = jasmine.createSpy()
displayBuffer.batchCharacterMeasurement ->
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth)
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '?', operatorWidth)
expect(displayBuffer.getScrollWidth()).toBe 10 * 63 + operatorWidth * 2 + cursorWidth
expect(changedSpy.callCount).toBe 1
describe "::getVisibleRowRange()", ->
beforeEach ->
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setHeight(100)
it "returns the first and the last visible rows", ->
displayBuffer.setScrollTop(0)
expect(displayBuffer.getVisibleRowRange()).toEqual [0, 9]
it "includes partially visible rows in the range", ->
displayBuffer.setScrollTop(5)
expect(displayBuffer.getVisibleRowRange()).toEqual [0, 10]
it "returns an empty range when lineHeight is 0", ->
displayBuffer.setLineHeightInPixels(0)
expect(displayBuffer.getVisibleRowRange()).toEqual [0, 0]
it "ends at last buffer row even if there's more space available", ->
displayBuffer.setHeight(150)
displayBuffer.setScrollTop(60)
expect(displayBuffer.getVisibleRowRange()).toEqual [0, 13]
expect(scrollSpy).toHaveBeenCalledWith(screenRange: [[8, 20], [8, 20]], options: {})
expect(scrollSpy).toHaveBeenCalledWith(screenRange: [[8, 20], [8, 20]], options: {center: true})
expect(scrollSpy).toHaveBeenCalledWith(screenRange: [[8, 20], [8, 20]], options: {center: false, reversed: true})
describe "::decorateMarker", ->
describe "when decorating gutters", ->

View File

@@ -0,0 +1,55 @@
DOMElementPool = require '../src/dom-element-pool'
describe "DOMElementPool", ->
domElementPool = null
beforeEach ->
domElementPool = new DOMElementPool
it "builds DOM nodes, recycling them when they are freed", ->
[div, span1, span2, span3, span4, span5] = elements = [
domElementPool.build("div")
domElementPool.build("span")
domElementPool.build("span")
domElementPool.build("span")
domElementPool.build("span")
domElementPool.build("span")
]
div.appendChild(span1)
span1.appendChild(span2)
div.appendChild(span3)
span3.appendChild(span4)
domElementPool.freeElementAndDescendants(div)
domElementPool.freeElementAndDescendants(span5)
expect(elements).toContain(domElementPool.build("div"))
expect(elements).toContain(domElementPool.build("span"))
expect(elements).toContain(domElementPool.build("span"))
expect(elements).toContain(domElementPool.build("span"))
expect(elements).toContain(domElementPool.build("span"))
expect(elements).toContain(domElementPool.build("span"))
expect(elements).not.toContain(domElementPool.build("div"))
expect(elements).not.toContain(domElementPool.build("span"))
it "forgets free nodes after being cleared", ->
span = domElementPool.build("span")
div = domElementPool.build("div")
domElementPool.freeElementAndDescendants(span)
domElementPool.freeElementAndDescendants(div)
domElementPool.clear()
expect(domElementPool.build("span")).not.toBe(span)
expect(domElementPool.build("div")).not.toBe(div)
it "throws an error when trying to free the same node twice", ->
div = domElementPool.build("div")
domElementPool.freeElementAndDescendants(div)
expect(-> domElementPool.freeElementAndDescendants(div)).toThrow()
it "throws an error when trying to free an invalid element", ->
expect(-> domElementPool.freeElementAndDescendants(null)).toThrow()
expect(-> domElementPool.freeElementAndDescendants(undefined)).toThrow()

View File

@@ -0,0 +1,12 @@
{
"name": "package-with-cached-incompatible-native-module",
"version": "1.0.0",
"main": "./main.js",
"_atomModuleCache": {
"extensions": {
".node": [
"node_modules/native-module/build/Release/native.node"
]
}
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "compatible-native-module",
"main": "./main.js"
}

View File

@@ -0,0 +1 @@
throw new Error("this simulates a native module's failure to load")

View File

@@ -0,0 +1,4 @@
{
"name": "native-module",
"main": "./main.js"
}

View File

@@ -0,0 +1,12 @@
{
"name": "package-with-ignored-incompatible-native-module",
"version": "1.0.0",
"main": "./main.js",
"_atomModuleCache": {
"extensions": {
".node": [
"node_modules/compatible-native-module/build/Release/native.node"
]
}
}
}

View File

@@ -1,3 +1,4 @@
{Git} = require 'atom'
{deprecate} = require 'grim'
deprecate('Fake task deprecation')
module.exports = ->

View File

@@ -11,7 +11,7 @@ describe "GitRepositoryProvider", ->
it "returns a Promise that resolves to a GitRepository", ->
waitsForPromise ->
provider = new GitRepositoryProvider atom.project
directory = new Directory path.join(__dirname, 'fixtures/git/master.git')
directory = new Directory path.join(__dirname, 'fixtures', 'git', 'master.git')
provider.repositoryForDirectory(directory).then (result) ->
expect(result).toBeInstanceOf GitRepository
expect(provider.pathToRepository[result.getPath()]).toBeTruthy()
@@ -24,11 +24,11 @@ describe "GitRepositoryProvider", ->
secondRepo = null
waitsForPromise ->
directory = new Directory path.join(__dirname, 'fixtures/git/master.git')
directory = new Directory path.join(__dirname, 'fixtures', 'git', 'master.git')
provider.repositoryForDirectory(directory).then (result) -> firstRepo = result
waitsForPromise ->
directory = new Directory path.join(__dirname, 'fixtures/git/master.git/objects')
directory = new Directory path.join(__dirname, 'fixtures', 'git', 'master.git', 'objects')
provider.repositoryForDirectory(directory).then (result) -> secondRepo = result
runs ->
@@ -56,6 +56,21 @@ describe "GitRepositoryProvider", ->
provider.repositoryForDirectory(directory).then (result) ->
expect(result).toBe null
describe "when specified a Directory with a valid gitfile-linked repository", ->
it "returns a Promise that resolves to a GitRepository", ->
waitsForPromise ->
provider = new GitRepositoryProvider atom.project
gitDirPath = path.join(__dirname, 'fixtures', 'git', 'master.git')
workDirPath = temp.mkdirSync('git-workdir')
fs.writeFileSync(path.join(workDirPath, '.git'), 'gitdir: ' + gitDirPath+'\n')
directory = new Directory workDirPath
provider.repositoryForDirectory(directory).then (result) ->
expect(result).toBeInstanceOf GitRepository
expect(provider.pathToRepository[result.getPath()]).toBeTruthy()
expect(result.statusTask).toBeTruthy()
expect(result.getType()).toBe 'git'
describe "when specified a Directory without existsSync()", ->
directory = null
provider = null

View File

@@ -3,6 +3,7 @@ GitRepository = require '../src/git-repository'
fs = require 'fs-plus'
path = require 'path'
Task = require '../src/task'
Project = require '../src/project'
copyRepository = ->
workingDirPath = temp.mkdirSync('atom-working-dir')
@@ -276,7 +277,7 @@ describe "GitRepository", ->
atom.workspace.open('file.txt')
runs ->
project2 = atom.project.testSerialization()
project2 = Project.deserialize(atom.project.serialize())
buffer = project2.getBuffers()[0]
waitsFor ->

View File

@@ -1,5 +1,6 @@
Gutter = require '../src/gutter'
GutterContainerComponent = require '../src/gutter-container-component'
DOMElementPool = require '../src/dom-element-pool'
describe "GutterContainerComponent", ->
[gutterContainerComponent] = []
@@ -22,9 +23,10 @@ describe "GutterContainerComponent", ->
mockTestState
beforeEach ->
domElementPool = new DOMElementPool
mockEditor = {}
mockMouseDown = ->
gutterContainerComponent = new GutterContainerComponent({editor: mockEditor, onMouseDown: mockMouseDown})
gutterContainerComponent = new GutterContainerComponent({editor: mockEditor, onMouseDown: mockMouseDown, domElementPool})
it "creates a DOM node with no child gutter nodes when it is initialized", ->
expect(gutterContainerComponent.getDomNode() instanceof HTMLElement).toBe true

View File

@@ -9,7 +9,7 @@ webdriverio = require "../../../build/node_modules/webdriverio"
AtomPath = remote.process.argv[0]
AtomLauncherPath = path.join(__dirname, "..", "helpers", "atom-launcher.sh")
ChromedriverPath = path.resolve(__dirname, '..', '..', '..', 'atom-shell', 'chromedriver', 'chromedriver')
ChromedriverPath = path.resolve(__dirname, '..', '..', '..', 'electron', 'chromedriver', 'chromedriver')
SocketPath = path.join(temp.mkdirSync("socket-dir"), "atom-#{process.env.USER}.sock")
ChromedriverPort = 9515
ChromedriverURLBase = "/wd/hub"

View File

@@ -6,20 +6,21 @@ return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED
# run them on Travis.
return if process.env.TRAVIS
fs = require "fs"
fs = require "fs-plus"
path = require "path"
temp = require("temp").track()
runAtom = require "./helpers/start-atom"
CSON = require "season"
describe "Starting Atom", ->
[tempDirPath, otherTempDirPath, atomHome] = []
atomHome = temp.mkdirSync('atom-home')
[tempDirPath, otherTempDirPath] = []
beforeEach ->
jasmine.useRealClock()
atomHome = temp.mkdirSync('atom-home')
fs.writeFileSync(path.join(atomHome, 'config.cson'), fs.readFileSync(path.join(__dirname, 'fixtures', 'atom-home', 'config.cson')))
fs.removeSync(path.join(atomHome, 'storage'))
tempDirPath = temp.mkdirSync("empty-dir")
otherTempDirPath = temp.mkdirSync("another-temp-dir")

View File

@@ -1,8 +1,6 @@
fs = require 'fs'
module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
{$, $$} = require '../src/space-pen-extensions'
window[key] = value for key, value of require '../vendor/jasmine'
{TerminalReporter} = require 'jasmine-tagged'
@@ -25,7 +23,7 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
log(str)
onComplete: (runner) ->
fs.closeSync(logStream) if logStream?
if process.env.JANKY_SHA1
if process.env.JANKY_SHA1 or process.env.CI
grim = require 'grim'
if grim.getDeprecationsLength() > 0
@@ -47,7 +45,9 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
jasmineEnv.addReporter(timeReporter)
jasmineEnv.setIncludedTags([process.platform])
$('body').append $$ -> @div id: 'jasmine-content'
jasmineContent = document.createElement('div')
jasmineContent.setAttribute('id', 'jasmine-content')
document.body.appendChild(jasmineContent)
jasmineEnv.execute()

Some files were not shown because too many files have changed in this diff Show More