Skip to content

Commit 98c1a3a

Browse files
Refactor Cake tasks (#4440)
* Node comes with NPM nowadays, so there’s not really a reason to install CoffeeScript the non-NPM way * The cake documentation tasks should each have build and watch modes following the same form * Refactor the build tasks to be more foolproof, including the parser unless it’s explicitly excluded * Abstract out testing built code, to prepare for watching the build task * Cake task to cut a new release * cake build:watch, based on https://github.com/GeoffreyBooth/coffeescript-gulp * Coding style * Tests shouldn’t write files in a watched folder * Don’t crash if the REPL test history file is already gone by the time we try to delete it
1 parent d84c94d commit 98c1a3a

File tree

6 files changed

+138
-81
lines changed

6 files changed

+138
-81
lines changed

Cakefile

Lines changed: 118 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -24,65 +24,31 @@ header = """
2424
*/
2525
"""
2626

27-
# Used in folder names like docs/v1
27+
# Used in folder names like `docs/v1`.
2828
majorVersion = parseInt CoffeeScript.VERSION.split('.')[0], 10
2929

30-
# Build the CoffeeScript language from source.
31-
build = (cb) ->
32-
files = fs.readdirSync 'src'
33-
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
34-
run ['-c', '-o', 'lib/coffee-script'].concat(files), cb
35-
36-
# Run a CoffeeScript through our node/coffee interpreter.
37-
run = (args, cb) ->
38-
proc = spawn 'node', ['bin/coffee'].concat(args)
39-
proc.stderr.on 'data', (buffer) -> console.log buffer.toString()
40-
proc.on 'exit', (status) ->
41-
process.exit(1) if status isnt 0
42-
cb() if typeof cb is 'function'
4330

4431
# Log a message with a color.
4532
log = (message, color, explanation) ->
4633
console.log color + message + reset + ' ' + (explanation or '')
4734

48-
option '-p', '--prefix [DIR]', 'set the installation prefix for `cake install`'
49-
50-
task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) ->
51-
base = options.prefix or '/usr/local'
52-
lib = "#{base}/lib/coffee-script"
53-
bin = "#{base}/bin"
54-
node = "~/.node_libraries/coffee-script"
55-
console.log "Installing CoffeeScript to #{lib}"
56-
console.log "Linking to #{node}"
57-
console.log "Linking 'coffee' to #{bin}/coffee"
58-
exec([
59-
"mkdir -p #{lib} #{bin}"
60-
"cp -rf bin lib LICENSE README.md package.json src #{lib}"
61-
"ln -sfn #{lib}/bin/coffee #{bin}/coffee"
62-
"ln -sfn #{lib}/bin/cake #{bin}/cake"
63-
"mkdir -p ~/.node_libraries"
64-
"ln -sfn #{lib}/lib/coffee-script #{node}"
65-
].join(' && '), (err, stdout, stderr) ->
66-
if err then console.log stderr.trim() else log 'done', green
67-
)
68-
69-
70-
task 'build', 'build the CoffeeScript language from source', build
71-
72-
task 'build:full', 'rebuild the source twice, and run the tests', ->
73-
build ->
74-
build ->
75-
csPath = './lib/coffee-script'
76-
csDir = path.dirname require.resolve csPath
7735

78-
for mod of require.cache when csDir is mod[0 ... csDir.length]
79-
delete require.cache[mod]
36+
spawnNodeProcess = (args, output = 'stderr', callback) ->
37+
relayOutput = (buffer) -> console.log buffer.toString()
38+
proc = spawn 'node', args
39+
proc.stdout.on 'data', relayOutput if output is 'both' or output is 'stdout'
40+
proc.stderr.on 'data', relayOutput if output is 'both' or output is 'stderr'
41+
proc.on 'exit', (status) -> callback(status) if typeof callback is 'function'
8042

81-
unless runTests require csPath
82-
process.exit 1
43+
# Run a CoffeeScript through our node/coffee interpreter.
44+
run = (args, callback) ->
45+
spawnNodeProcess ['bin/coffee'].concat(args), 'stderr', (status) ->
46+
process.exit(1) if status isnt 0
47+
callback() if typeof callback is 'function'
8348

8449

85-
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
50+
# Build the CoffeeScript language from source.
51+
buildParser = ->
8652
helpers.extend global, require 'util'
8753
require 'jison'
8854
parser = require('./lib/coffee-script/grammar').parser.generate()
@@ -95,8 +61,62 @@ task 'build:parser', 'rebuild the Jison parser (run build first)', ->
9561
source = fs"""
9662
fs.writeFileSync 'lib/coffee-script/parser.js', parser
9763

64+
buildExceptParser = (callback) ->
65+
files = fs.readdirSync 'src'
66+
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
67+
run ['-c', '-o', 'lib/coffee-script'].concat(files), callback
68+
69+
build = (callback) ->
70+
buildParser()
71+
buildExceptParser callback
72+
73+
testBuiltCode = (watch = no) ->
74+
csPath = './lib/coffee-script'
75+
csDir = path.dirname require.resolve csPath
76+
77+
for mod of require.cache when csDir is mod[0 ... csDir.length]
78+
delete require.cache[mod]
79+
80+
testResults = runTests require csPath
81+
unless watch
82+
process.exit 1 unless testResults
83+
84+
buildAndTest = (includingParser = yes, harmony = no) ->
85+
process.stdout.write '\x1Bc' # Clear terminal screen.
86+
execSync 'git checkout lib/*', stdio: [0,1,2] # Reset the generated compiler.
87+
88+
buildArgs = ['bin/cake']
89+
buildArgs.push if includingParser then 'build' else 'build:except-parser'
90+
log "building#{if includingParser then ', including parser' else ''}...", green
91+
spawnNodeProcess buildArgs, 'both', ->
92+
log 'testing...', green
93+
testArgs = if harmony then ['--harmony'] else []
94+
testArgs = testArgs.concat ['bin/cake', 'test']
95+
spawnNodeProcess testArgs, 'both'
9896

99-
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
97+
watchAndBuildAndTest = (harmony = no) ->
98+
buildAndTest yes, harmony
99+
fs.watch 'src/', interval: 200, (eventType, filename) ->
100+
if eventType is 'change'
101+
log "src/#{filename} changed, rebuilding..."
102+
buildAndTest (filename is 'grammar.coffee'), harmony
103+
fs.watch 'test/', {interval: 200, recursive: yes}, (eventType, filename) ->
104+
if eventType is 'change'
105+
log "test/#{filename} changed, rebuilding..."
106+
buildAndTest no, harmony
107+
108+
109+
task 'build', 'build the CoffeeScript compiler from source', build
110+
111+
task 'build:parser', 'build the Jison parser only', buildParser
112+
113+
task 'build:except-parser', 'build the CoffeeScript compiler, except for the Jison parser', buildExceptParser
114+
115+
task 'build:full', 'build the CoffeeScript compiler from source twice, and run the tests', ->
116+
build ->
117+
build testBuiltCode
118+
119+
task 'build:browser', 'build the merged script for inclusion in the browser', ->
100120
code = """
101121
require['../../package.json'] = (function() {
102122
return #{fs.readFileSync "./package.json"};
@@ -137,8 +157,14 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
137157
console.log "built ... running browser tests:"
138158
invoke 'test:browser'
139159

160+
task 'build:watch', 'watch and continually rebuild the CoffeeScript compiler, running tests on each build', ->
161+
watchAndBuildAndTest()
162+
163+
task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript compiler, running harmony tests on each build', ->
164+
watchAndBuildAndTest yes
165+
140166

141-
task 'doc:site', 'watch and continually rebuild the documentation for the website', ->
167+
buildDocs = (watch = no) ->
142168
# Constants
143169
indexFile = 'documentation/index.html'
144170
versionedSourceFolder = "documentation/v#{majorVersion}"
@@ -211,12 +237,19 @@ task 'doc:site', 'watch and continually rebuild the documentation for the websit
211237
fs.symlinkSync "v#{majorVersion}/index.html", 'docs/index.html'
212238
catch exception
213239

214-
for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder]
215-
fs.watch target, interval: 200, renderIndex
216-
log 'watching...' , green
240+
if watch
241+
for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder]
242+
fs.watch target, interval: 200, renderIndex
243+
log 'watching...', green
217244

245+
task 'doc:site', 'build the documentation for the website', ->
246+
buildDocs()
218247

219-
task 'doc:test', 'watch and continually rebuild the browser-based tests', ->
248+
task 'doc:site:watch', 'watch and continually rebuild the documentation for the website', ->
249+
buildDocs yes
250+
251+
252+
buildDocTests = (watch = no) ->
220253
# Constants
221254
testFile = 'documentation/test.html'
222255
testsSourceFolder = 'test'
@@ -254,14 +287,40 @@ task 'doc:test', 'watch and continually rebuild the browser-based tests', ->
254287
fs.writeFileSync "#{outputFolder}/test.html", output
255288
log 'compiled', green, "#{testFile}#{outputFolder}/test.html"
256289

257-
for target in [testFile, testsSourceFolder]
258-
fs.watch target, interval: 200, renderTest
259-
log 'watching...' , green
290+
if watch
291+
for target in [testFile, testsSourceFolder]
292+
fs.watch target, interval: 200, renderTest
293+
log 'watching...', green
294+
295+
task 'doc:test', 'build the browser-based tests', ->
296+
buildDocTests()
297+
298+
task 'doc:test:watch', 'watch and continually rebuild the browser-based tests', ->
299+
buildDocTests yes
300+
301+
302+
buildAnnotatedSource = (watch = no) ->
303+
do generateAnnotatedSource = ->
304+
exec "node_modules/docco/bin/docco src/*.*coffee --output docs/v#{majorVersion}/annotated-source", (err) -> throw err if err
305+
log 'generated', green, "annotated source in docs/v#{majorVersion}/annotated-source/"
306+
307+
if watch
308+
fs.watch 'src/', interval: 200, generateAnnotatedSource
309+
log 'watching...', green
310+
311+
task 'doc:source', 'build the annotated source documentation', ->
312+
buildAnnotatedSource()
260313

314+
task 'doc:source:watch', 'watch and continually rebuild the annotated source documentation', ->
315+
buildAnnotatedSource yes
261316

262-
task 'doc:source', 'rebuild the annotated source documentation', ->
263-
exec "node_modules/docco/bin/docco src/*.*coffee --output docs/v#{majorVersion}/annotated-source", (err) -> throw err if err
264317

318+
task 'release', 'build and test the CoffeeScript source, and build the documentation', ->
319+
invoke 'build:full'
320+
invoke 'build:browser'
321+
invoke 'doc:site'
322+
invoke 'doc:test'
323+
invoke 'doc:source'
265324

266325
task 'bench', 'quick benchmark of compilation time', ->
267326
{Rewriter} = require './lib/coffee-script/rewriter'

README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,10 @@ CoffeeScript is a little language that compiles into JavaScript.
2525
If you have the node package manager, npm, installed:
2626

2727
```shell
28-
npm install -g coffee-script
28+
npm install --global coffee-script
2929
```
3030

31-
Leave off the `-g` if you don't wish to install globally. If you don't wish to use npm:
32-
33-
```shell
34-
git clone https://github.com/jashkenas/coffeescript.git
35-
sudo coffeescript/bin/cake install
36-
```
31+
Leave off the `--global` if you don’t wish to install globally.
3732

3833
## Getting Started
3934

@@ -53,7 +48,7 @@ For documentation, usage, and examples, see: http://coffeescript.org/
5348

5449
To suggest a feature or report a bug: http://github.com/jashkenas/coffeescript/issues
5550

56-
If you'd like to chat, drop by #coffeescript on Freenode IRC.
51+
If youd like to chat, drop by #coffeescript on Freenode IRC.
5752

5853
The source repository: https://github.com/jashkenas/coffeescript.git
5954

docs/v1/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,9 +2584,9 @@ <h2>Resources</h2><ul>
25842584
<li><p><a href="http://github.com/jashkenas/coffeescript/">Source Code</a><br>
25852585
Use <code>bin/coffee</code> to test your changes,<br>
25862586
<code>bin/cake test</code> to run the test suite,<br>
2587-
<code>bin/cake build</code> to rebuild the CoffeeScript compiler, and<br>
2588-
<code>bin/cake build:parser</code> to regenerate the Jison parser if you’re working on the grammar.</p>
2589-
<p><code>git checkout lib &amp;&amp; bin/cake build:full</code> is a good command to run when you’re working on the core language. It’ll refresh the lib directory (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.</p>
2587+
<code>bin/cake build</code> to rebuild the full CoffeeScript compiler, and<br>
2588+
<code>bin/cake build:except-parser</code> to recompile much faster if you’re not editing <code>grammar.coffee</code>.</p>
2589+
<p><code>git checkout lib &amp;&amp; bin/cake build:full</code> is a good command to run when you’re working on the core language. It’ll refresh the <code>lib</code> folder (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.</p>
25902590
</li>
25912591
<li><a href="v1/test.html">Browser Tests</a><br>
25922592
Run CoffeeScript’s test suite in your current browser.</li>

documentation/sections/resources.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* [Source Code](http://github.com/jashkenas/coffeescript/)<br>
44
Use `bin/coffee` to test your changes,<br>
55
`bin/cake test` to run the test suite,<br>
6-
`bin/cake build` to rebuild the CoffeeScript compiler, and<br>
7-
`bin/cake build:parser` to regenerate the Jison parser if you’re working on the grammar.
6+
`bin/cake build` to rebuild the full CoffeeScript compiler, and<br>
7+
`bin/cake build:except-parser` to recompile much faster if you’re not editing `grammar.coffee`.
88

9-
`git checkout lib && bin/cake build:full` is a good command to run when you’re working on the core language. It’ll refresh the lib directory (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.
9+
`git checkout lib && bin/cake build:full` is a good command to run when you’re working on the core language. It’ll refresh the `lib` folder (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.
1010
* [Browser Tests](v<%= majorVersion %>/test.html)<br>
1111
Run CoffeeScript’s test suite in your current browser.
1212
* [CoffeeScript Issues](http://github.com/jashkenas/coffeescript/issues)<br>

test/error_messages.coffee

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,21 @@ if require?
7171

7272
test "#2849: compilation error in a require()d file", ->
7373
# Create a temporary file to require().
74-
ok not fs.existsSync 'test/syntax-error.coffee'
75-
fs.writeFileSync 'test/syntax-error.coffee', 'foo in bar or in baz'
74+
tempFile = path.join os.tmpdir(), 'syntax-error.coffee'
75+
ok not fs.existsSync tempFile
76+
fs.writeFileSync tempFile, 'foo in bar or in baz'
7677

7778
try
78-
assertErrorFormat '''
79-
require './test/syntax-error'
80-
''',
79+
assertErrorFormat """
80+
require '#{tempFile}'
81+
""",
8182
"""
82-
#{path.join __dirname, 'syntax-error.coffee'}:1:15: error: unexpected in
83+
#{fs.realpathSync tempFile}:1:15: error: unexpected in
8384
foo in bar or in baz
8485
^^
8586
"""
8687
finally
87-
fs.unlinkSync 'test/syntax-error.coffee'
88+
fs.unlinkSync tempFile
8889

8990
test "#3890 Error.prepareStackTrace doesn't throw an error if a compiled file is deleted", ->
9091
# Adapted from https://github.com/atom/coffee-cash/blob/master/spec/coffee-cash-spec.coffee

test/repl.coffee

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,6 @@ testRepl "keeps running after runtime error", (input, output) ->
109109
eq 'undefined', output.lastWrite()
110110

111111
process.on 'exit', ->
112-
fs.unlinkSync historyFile
112+
try
113+
fs.unlinkSync historyFile
114+
catch exception # Already deleted, nothing else to do.

0 commit comments

Comments
 (0)