Skip to content

Commit

Permalink
fix top-level errors, somewhat
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed Nov 23, 2024
1 parent d29ef4e commit b08e917
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 38 deletions.
44 changes: 40 additions & 4 deletions Cakefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ option null, '--no-color', 'disable colored output'
task = (name, description, action) ->
global.task name, description, ({level = 'log', ...opts} = {}) ->
setupStyler {colors: not opts['no-color']}
setupConsole {level}
action {...opts}
console = setupConsole {level}
try
await Promise.resolve action {...opts}
catch e
if e instanceof TopLevelError
e.printAndExit console
throw e

sha256 = -> createHash 'sha256'

Expand Down Expand Up @@ -91,16 +96,47 @@ buildParser = ->
parserTask = new JisonParser
await parserTask.cachedExecute console


class TopLevelError extends AggregateError
printAndExit: (console) ->
aggregateQueue = [@]

while aggregateQueue.length > 0
e = aggregateQueue.shift()
console.error e.message if e.message
if e instanceof AggregateError
aggregateQueue.push ...e.errors

process.exit 1

@executeParallel: (tasks) -> Promise.allSettled(tasks).then (results) =>
failures = (reason for {status, value, reason} in results when status is 'rejected')
if failures.length > 0
Promise.reject new @ failures


class CompileFailures extends TopLevelError
constructor: (errors) ->
message = "#{errors.length} compiles failed"
super errors, message


buildExceptParser = ->
compileRequests = for file in await fs.promises.readdir 'src'
{name, ext} = path.parse file
continue unless ext in ['.coffee', '.litcoffee']
coffeeSource = path.join 'src', file
jsOut = path.join 'lib/coffeescript', "#{name}.js"
new CompileSources {coffeeSource, jsOut}
Promise.all compileRequests.map (r) -> r.cachedExecute console

build = -> Promise.all [buildParser(), buildExceptParser()]
CompileFailures.executeParallel compileRequests.map (r) -> r.cachedExecute console


class FullBuildError extends TopLevelError


build = -> FullBuildError.executeParallel [buildParser(), buildExceptParser()]


transpile = (code, options = {}) ->
options.minify = process.env.MINIFY isnt 'false'
Expand Down
7 changes: 3 additions & 4 deletions build-support/build-deps.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ BuildTask, ChecksumFiles } = require './caching'
{ collectProcess, getCapture, invokeProcess } = require './subprocess'
{ BuildTask, ChecksumFiles } = require './caching'
{ collectNone, getCapture, invokeProcess } = require './subprocess'


exports.BuildDeps = class BuildDeps extends BuildTask
Expand All @@ -16,7 +16,6 @@ exports.BuildDeps = class BuildDeps extends BuildTask

execute: ->
capture = getCapture 'stderr'
collect = collectProcess -> null
proc = await invokeProcess 'npm', ['install', '.']
capture proc
await collect proc
await collectNone proc
29 changes: 18 additions & 11 deletions build-support/caching.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ class Attestation
make: ->
[inputs, outputs] = await Promise.all [
@inputSources.digestAll()
@outputSources.digestAll().catch (e) => Promise.reject if e instanceof Content.Unavailable
new @constructor.OutputUnavailable e
else e
@outputSources.digestAll().catch (e) => Promise.reject switch
when e instanceof Content.Unavailable
new @constructor.OutputUnavailable e
else e
]
ret =
inputs: {}
Expand Down Expand Up @@ -123,10 +124,15 @@ class Attestation
@constructor.objectEquals cached, generated


exports.TaskError = class TaskError extends Error
printAndExit: (task, console) ->
console.error "failed: #{task.print()}"
process.exit 1
exports.TaskFailed = class TaskFailed extends Error
constructor: (task, cause) ->
message = "task failed: #{task.print()}\n#{cause.message}"
super message, {cause}
@task = task


# exports.ManyFailures = class ManyFailures extends AggregateError
# constructor: (errors, message) ->


exports.BuildTask = class BuildTask
Expand Down Expand Up @@ -164,10 +170,11 @@ exports.BuildTask = class BuildTask
console.log @print()
startTask = performance.now()

await @execute(console).catch (e) => switch
when e instanceof TaskError
e.printAndExit @, console
else Promise.reject e
# await @execute(console).catch (e) => switch
# when e instanceof TaskError
# e.printAndExit @, console
# else Promise.reject e
await @execute(console).catch (e) => Promise.reject new TaskFailed @, e

endTask = performance.now()
console.info "task '#{@identifier()}' complete (#{endTask - startTask} ms)"
Expand Down
6 changes: 4 additions & 2 deletions build-support/console.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ exports.CakeConsole = class CakeConsole extends Console


exports.setupConsole = ({level}) ->
return if global.cakeConsole?
global.console = global.cakeConsole = CakeConsole.stdio {level}
if global.cakeConsole?
return global.cakeConsole
global.console = global.cakeConsole = cakeConsole = CakeConsole.stdio {level}
console.debug "log level = #{level}"
cakeConsole
8 changes: 5 additions & 3 deletions build-support/parser.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ BuildTask, ChecksumFiles } = require './caching'
{ spawnNodeProcess } = require './subprocess'
{ BuildTask, ChecksumFiles } = require './caching'
{ invokeProcess, captureErr } = require './subprocess'

exports.JisonParser = class JisonParser extends BuildTask
identifier: -> 'jison-parser'
Expand All @@ -16,4 +16,6 @@ exports.JisonParser = class JisonParser extends BuildTask
outputSources: -> new ChecksumFiles [@parserPath]
print: -> "jison generate: #{@grammarPath} -> #{@parserPath}"

execute: -> await spawnNodeProcess [@coffeeBin, @jisonScript, @grammarPath, @parserPath]
execute: ->
proc = await invokeProcess process.execPath, [@coffeeBin, @jisonScript, @grammarPath, @parserPath]
await captureErr proc
27 changes: 13 additions & 14 deletions build-support/subprocess.coffee
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
{ spawn } = require 'child_process'
process = require 'process'
{ TaskError } = require './caching'


exports.SubprocessError = class SubprocessError extends TaskError
constructor: (@child, ...rest) -> super ...rest
exports.SubprocessError = class SubprocessError extends Error
constructor: (child, message, ...rest) ->
message = "process [#{child.spawnargs.join ', '}] failed: #{message}"
super message, ...rest
@child = child

exe: -> @child.spawnfile
args: -> @child.spawnargs

printAndExit: (task, console) ->
console.error "process '#{@exe()}' [#{@args().join ', '}] failed: #{@message}"
super task, console

exports.SpawnFailed = class SpawnFailed extends SubprocessError
constructor: (child, cause) -> super child, 'process spawn failed: #{cause.message}', {cause}

Expand All @@ -27,13 +26,13 @@ exports.NonZeroExit = class NonZeroExit extends ProcessCompletedError
exports.Aborted = class Aborted extends ProcessCompletedError
constructor: (child, cause) -> super child, 'process aborted', {cause}

exports.OutputCapturedError = class OutputCapturedError extends ProcessCompletedError
constructor: (@capturedOutput, cause) ->
super cause.child, cause.message, {cause}

printAndExit: (task, console) ->
process.stderr.write @capturedOutput
super task, console
exports.OutputCapturedError = class OutputCapturedError extends Error
constructor: (capturedOutput, cause) ->
message = if capturedOutput
"#{cause.message}\n#{capturedOutput}"
else cause.message
super message, {cause}
@capturedOutput = capturedOutput


# Async process spawning.
Expand Down

0 comments on commit b08e917

Please sign in to comment.