2013-05-30 21:22:30 +04:00
|
|
|
{spawn} = require 'child_process'
|
2013-05-30 04:35:00 +04:00
|
|
|
fs = require 'fs'
|
|
|
|
path = require 'path'
|
|
|
|
_ = require 'underscore'
|
|
|
|
CSON = require 'season'
|
|
|
|
|
2013-05-30 04:58:11 +04:00
|
|
|
BUILD_DIR = '/tmp/atom-build/atom-shell'
|
2013-05-30 04:49:46 +04:00
|
|
|
APP_NAME = 'Atom.app'
|
2013-05-31 00:21:54 +04:00
|
|
|
CONTENTS_DIR = path.join(BUILD_DIR, APP_NAME, 'Contents')
|
|
|
|
APP_DIR = path.join(CONTENTS_DIR, 'Resources', 'app')
|
2013-05-30 04:49:46 +04:00
|
|
|
INSTALL_DIR = path.join('/Applications', APP_NAME)
|
2013-05-30 03:39:37 +04:00
|
|
|
|
2013-05-29 04:30:09 +04:00
|
|
|
module.exports = (grunt) ->
|
2013-05-30 21:22:30 +04:00
|
|
|
exec = (command, args, options, callback) ->
|
2013-05-30 21:47:59 +04:00
|
|
|
if _.isFunction(args)
|
|
|
|
options = args
|
|
|
|
args = []
|
2013-05-30 21:22:30 +04:00
|
|
|
if _.isFunction(options)
|
|
|
|
callback = options
|
|
|
|
options = undefined
|
|
|
|
|
|
|
|
spawned = spawn(command, args, options)
|
|
|
|
stdoutChunks = []
|
|
|
|
spawned.stdout.on 'data', (data) -> stdoutChunks.push(data)
|
|
|
|
stderrChunks = []
|
|
|
|
spawned.stderr.on 'data', (data) -> stderrChunks.push(data)
|
|
|
|
spawned.on 'close', (code) ->
|
2013-05-31 02:24:21 +04:00
|
|
|
if code is 0 or options?.ignoreFailures
|
2013-05-30 21:22:30 +04:00
|
|
|
callback(null, Buffer.concat(stdoutChunks).toString())
|
|
|
|
else if stderrChunks.length > 0
|
|
|
|
error = Buffer.concat(stderrChunks).toString()
|
|
|
|
grunt.log.error(error)
|
|
|
|
callback(error)
|
|
|
|
else
|
2013-05-31 00:39:53 +04:00
|
|
|
error = "`#{command}` Failed with code: #{code}"
|
2013-05-30 21:22:30 +04:00
|
|
|
grunt.log.error(error)
|
2013-05-31 00:39:53 +04:00
|
|
|
callback(error)
|
2013-05-30 21:22:30 +04:00
|
|
|
|
2013-05-30 09:53:52 +04:00
|
|
|
cp = (source, destination, {filter}={}) ->
|
2013-05-31 05:00:14 +04:00
|
|
|
copyFile = (source, destination) ->
|
|
|
|
if grunt.file.isLink(source)
|
|
|
|
grunt.file.mkdir(path.dirname(destination))
|
|
|
|
fs.symlinkSync(fs.readlinkSync(source), destination)
|
|
|
|
else
|
|
|
|
grunt.file.copy(source, destination)
|
2013-05-30 20:23:14 +04:00
|
|
|
|
2013-05-31 05:00:14 +04:00
|
|
|
if grunt.file.exists(destination)
|
|
|
|
fs.chmodSync(destination, fs.statSync(source).mode)
|
2013-05-30 20:23:14 +04:00
|
|
|
|
2013-05-31 05:00:14 +04:00
|
|
|
if grunt.file.isDir(source)
|
|
|
|
grunt.file.recurse source, (sourcePath, rootDirectory, subDirectory='', filename) ->
|
|
|
|
unless filter?.test(sourcePath)
|
|
|
|
copyFile(sourcePath, path.join(destination, subDirectory, filename))
|
2013-05-30 05:38:15 +04:00
|
|
|
else
|
2013-05-31 05:00:14 +04:00
|
|
|
copyFile(source, destination)
|
|
|
|
|
2013-05-30 05:38:15 +04:00
|
|
|
grunt.log.writeln("Copied #{source.cyan} to #{destination.cyan}.")
|
|
|
|
|
2013-05-30 09:38:02 +04:00
|
|
|
mkdir = (args...) -> grunt.file.mkdir(args...)
|
2013-05-30 22:19:45 +04:00
|
|
|
rm = (args...) ->
|
|
|
|
grunt.file.delete(args..., force: true) if grunt.file.exists(args...)
|
2013-05-30 09:38:02 +04:00
|
|
|
|
2013-05-29 04:30:09 +04:00
|
|
|
grunt.initConfig
|
|
|
|
pkg: grunt.file.readJSON('package.json')
|
|
|
|
|
2013-05-30 04:35:00 +04:00
|
|
|
coffee:
|
|
|
|
options:
|
|
|
|
sourceMap: true
|
|
|
|
|
|
|
|
glob_to_multiple:
|
|
|
|
expand: true
|
|
|
|
src: [
|
|
|
|
'src/**/*.coffee'
|
|
|
|
'static/**/*.coffee'
|
|
|
|
'vendor/**/*.coffee'
|
|
|
|
]
|
|
|
|
dest: APP_DIR
|
|
|
|
ext: '.js'
|
|
|
|
|
|
|
|
less:
|
|
|
|
options:
|
|
|
|
paths: [
|
|
|
|
'static'
|
|
|
|
'vendor'
|
|
|
|
]
|
|
|
|
glob_to_multiple:
|
|
|
|
expand: true
|
|
|
|
src: [
|
|
|
|
'src/**/*.less'
|
|
|
|
'static/**/*.less'
|
|
|
|
'themes/**/*.less'
|
|
|
|
]
|
|
|
|
dest: APP_DIR
|
|
|
|
ext: '.css'
|
|
|
|
|
|
|
|
cson:
|
|
|
|
glob_to_multiple:
|
|
|
|
expand: true
|
|
|
|
src: [
|
|
|
|
'src/**/*.cson'
|
|
|
|
'static/**/*.cson'
|
|
|
|
'themes/**/*.cson'
|
|
|
|
]
|
|
|
|
dest: APP_DIR
|
|
|
|
ext: '.json'
|
|
|
|
|
2013-05-29 04:30:09 +04:00
|
|
|
coffeelint:
|
|
|
|
options:
|
2013-06-06 19:16:23 +04:00
|
|
|
no_empty_param_list:
|
|
|
|
level: 'error'
|
2013-05-29 04:30:09 +04:00
|
|
|
max_line_length:
|
|
|
|
level: 'ignore'
|
|
|
|
|
|
|
|
src: ['src/**/*.coffee']
|
2013-05-29 22:50:53 +04:00
|
|
|
test: [
|
|
|
|
'spec/*.coffee'
|
|
|
|
'spec/app/**/*.coffee'
|
|
|
|
'spec/stdlib/**/*.coffee'
|
|
|
|
]
|
2013-05-29 04:30:09 +04:00
|
|
|
|
2013-05-29 23:13:47 +04:00
|
|
|
csslint:
|
|
|
|
options:
|
|
|
|
'adjoining-classes': false
|
|
|
|
'fallback-colors': false
|
2013-06-12 03:34:48 +04:00
|
|
|
'vendor-prefix': false
|
|
|
|
src: [
|
|
|
|
'src/**/*.css',
|
|
|
|
'static/**/*.css'
|
|
|
|
'themes/**/*.css'
|
|
|
|
]
|
2013-05-29 04:30:09 +04:00
|
|
|
|
|
|
|
grunt.loadNpmTasks('grunt-coffeelint')
|
2013-05-29 23:13:47 +04:00
|
|
|
grunt.loadNpmTasks('grunt-contrib-csslint')
|
2013-05-30 04:35:00 +04:00
|
|
|
grunt.loadNpmTasks('grunt-contrib-coffee')
|
|
|
|
grunt.loadNpmTasks('grunt-contrib-less')
|
|
|
|
|
|
|
|
grunt.registerMultiTask 'cson', 'Compile CSON files to JSON', ->
|
|
|
|
for mapping in @files
|
|
|
|
source = mapping.src[0]
|
|
|
|
destination = mapping.dest
|
|
|
|
try
|
|
|
|
object = CSON.readFileSync(source)
|
|
|
|
if !_.isObject(object) or _.isArray(object)
|
|
|
|
grunt.log.error("#{source} does not contain a root object")
|
|
|
|
return false
|
|
|
|
mkdir path.dirname(destination)
|
|
|
|
CSON.writeFileSync(destination, object)
|
|
|
|
grunt.log.writeln("File #{destination.cyan} created.")
|
|
|
|
catch e
|
|
|
|
grunt.log.error("Parsing #{source} failed: #{e.message}")
|
|
|
|
return false
|
2013-05-29 04:30:09 +04:00
|
|
|
|
2013-05-30 21:22:30 +04:00
|
|
|
grunt.registerTask 'postbuild', 'Run postbuild scripts', ->
|
|
|
|
done = @async()
|
|
|
|
|
|
|
|
exec 'git', ['rev-parse', '--short', 'HEAD'], (error, version) ->
|
|
|
|
if error?
|
|
|
|
done(false)
|
|
|
|
else
|
|
|
|
version = version.trim()
|
|
|
|
grunt.file.write(path.resolve(APP_DIR, '..', 'version'), version)
|
|
|
|
|
2013-05-30 21:47:59 +04:00
|
|
|
commands = []
|
|
|
|
commands.push (callback) ->
|
2013-05-30 21:22:30 +04:00
|
|
|
args = [
|
|
|
|
version
|
|
|
|
'resources/mac/app-Info.plist'
|
|
|
|
'Atom.app/Contents/Info.plist'
|
|
|
|
]
|
|
|
|
exec('script/generate-info-plist', args, env: {BUILT_PRODUCTS_DIR: BUILD_DIR}, callback)
|
|
|
|
|
2013-05-30 21:47:59 +04:00
|
|
|
commands.push (result, callback) ->
|
2013-05-30 21:22:30 +04:00
|
|
|
args = [
|
|
|
|
version
|
|
|
|
'resources/mac/helper-Info.plist'
|
|
|
|
'Atom.app/Contents/Frameworks/Atom Helper.app/Contents/Info.plist'
|
|
|
|
]
|
|
|
|
exec('script/generate-info-plist', args, env: {BUILT_PRODUCTS_DIR: BUILD_DIR}, callback)
|
|
|
|
|
2013-05-30 21:47:59 +04:00
|
|
|
grunt.util.async.waterfall commands, (error) -> done(!error?)
|
2013-05-30 21:22:30 +04:00
|
|
|
|
2013-05-30 03:39:37 +04:00
|
|
|
grunt.registerTask 'clean', 'Delete all build files', ->
|
|
|
|
rm BUILD_DIR
|
|
|
|
rm '/tmp/atom-coffee-cache'
|
|
|
|
rm '/tmp/atom-cached-atom-shells'
|
|
|
|
rm 'node_modules'
|
|
|
|
rm 'atom-shell'
|
|
|
|
rm 'cef'
|
|
|
|
rm 'node'
|
|
|
|
rm 'prebuilt-cef'
|
|
|
|
|
2013-05-30 04:35:00 +04:00
|
|
|
grunt.registerTask 'build', 'Build the application', ->
|
|
|
|
rm BUILD_DIR
|
2013-05-30 04:58:11 +04:00
|
|
|
mkdir path.dirname(BUILD_DIR)
|
|
|
|
cp 'atom-shell', BUILD_DIR
|
2013-05-30 05:30:29 +04:00
|
|
|
|
|
|
|
mkdir APP_DIR
|
|
|
|
|
2013-05-30 05:38:15 +04:00
|
|
|
cp 'atom.sh', path.join(APP_DIR, 'atom.sh')
|
|
|
|
cp 'package.json', path.join(APP_DIR, 'package.json')
|
2013-05-30 05:30:29 +04:00
|
|
|
|
|
|
|
directories = [
|
|
|
|
'benchmark'
|
|
|
|
'dot-atom'
|
|
|
|
'node_modules'
|
|
|
|
'spec'
|
|
|
|
'vendor'
|
|
|
|
]
|
2013-05-30 05:47:34 +04:00
|
|
|
cp directory, path.join(APP_DIR, directory) for directory in directories
|
2013-05-30 05:30:29 +04:00
|
|
|
|
|
|
|
cp 'src', path.join(APP_DIR, 'src'), filter: /.+\.(cson|coffee|less)$/
|
|
|
|
cp 'static', path.join(APP_DIR, 'static'), filter: /.+\.less$/
|
|
|
|
cp 'themes', path.join(APP_DIR, 'themes'), filter: /.+\.(cson|less)$/
|
|
|
|
|
2013-05-30 21:22:30 +04:00
|
|
|
grunt.file.recurse path.join('resources/mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
|
|
|
|
unless /.+\.plist/.test(sourcePath)
|
|
|
|
grunt.file.copy(sourcePath, path.resolve(APP_DIR, '..', subDirectory, filename))
|
|
|
|
|
|
|
|
grunt.task.run('compile', 'postbuild')
|
2013-05-30 04:35:00 +04:00
|
|
|
|
2013-05-30 04:49:46 +04:00
|
|
|
grunt.registerTask 'install', 'Install the built application', ->
|
|
|
|
rm INSTALL_DIR
|
2013-05-30 05:44:28 +04:00
|
|
|
mkdir path.dirname(INSTALL_DIR)
|
2013-05-30 04:49:46 +04:00
|
|
|
cp path.join(BUILD_DIR, APP_NAME), INSTALL_DIR
|
|
|
|
|
2013-05-30 21:47:59 +04:00
|
|
|
grunt.registerTask 'bootstrap', 'Bootstrap modules and atom-shell', ->
|
|
|
|
done = @async()
|
|
|
|
commands = []
|
|
|
|
commands.push (callback) ->
|
|
|
|
exec('script/bootstrap', callback)
|
|
|
|
commands.push (result, callback) ->
|
|
|
|
exec('script/update-atom-shell', callback)
|
|
|
|
grunt.util.async.waterfall commands, (error) -> done(!error?)
|
|
|
|
|
2013-05-31 00:21:54 +04:00
|
|
|
grunt.registerTask 'test', 'Run the specs', ->
|
|
|
|
done = @async()
|
|
|
|
commands = []
|
|
|
|
commands.push (callback) ->
|
2013-05-31 00:41:20 +04:00
|
|
|
exec('pkill', ['Atom'], ignoreFailures: true, callback)
|
2013-05-31 00:21:54 +04:00
|
|
|
commands.push (result, callback) ->
|
2013-05-31 02:56:15 +04:00
|
|
|
exec(path.join(CONTENTS_DIR, 'MacOS', 'Atom'), ['--test', "--resource-path=#{__dirname}"], callback)
|
2013-05-31 00:21:54 +04:00
|
|
|
grunt.util.async.waterfall commands, (error) -> done(!error?)
|
|
|
|
|
2013-05-30 04:35:00 +04:00
|
|
|
grunt.registerTask('compile', ['coffee', 'less', 'cson'])
|
2013-05-30 03:45:12 +04:00
|
|
|
grunt.registerTask('lint', ['coffeelint', 'csslint'])
|
2013-05-31 00:27:13 +04:00
|
|
|
grunt.registerTask('ci', ['clean', 'bootstrap', 'build', 'test'])
|
2013-05-30 04:35:00 +04:00
|
|
|
grunt.registerTask('default', ['lint', 'build'])
|