diff --git a/CHANGELOG.md b/CHANGELOG.md index b3972376..5ba8e7d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Fix issue where emulated builds broke Docker `ARG` commands +### Added + +- Fix issue when using resin deploy with non-standard stdin (e.g. git bash on windows) + ## [6.0.0] - 2017-06-26 ### Added diff --git a/build/actions/build.js b/build/actions/build.js index e2ea7d98..6ea4bbbd 100644 --- a/build/actions/build.js +++ b/build/actions/build.js @@ -43,8 +43,8 @@ module.exports = { } ]), action: function(params, options, done) { - var logging; - logging = require('../utils/logging'); - return dockerUtils.runBuild(params, options, getBundleInfo, logging.getLogStreams()).asCallback(done); + var Logger; + Logger = require('../utils/logger'); + return dockerUtils.runBuild(params, options, getBundleInfo, new Logger()).asCallback(done); } }; diff --git a/build/actions/deploy.js b/build/actions/deploy.js index c007a04f..cba9ec4f 100644 --- a/build/actions/deploy.js +++ b/build/actions/deploy.js @@ -1,5 +1,5 @@ // Generated by CoffeeScript 1.12.6 -var Promise, dockerUtils, formatImageName, getBuilderLogPushEndpoint, getBuilderPushEndpoint, getBundleInfo, parseInput, performUpload, renderProgress, showPushProgress, updatePushProgress, uploadLogs, uploadToPromise; +var Promise, dockerUtils, formatImageName, getBuilderLogPushEndpoint, getBuilderPushEndpoint, getBundleInfo, parseInput, performUpload, showPushProgress, uploadLogs, uploadToPromise; Promise = require('bluebird'); @@ -51,36 +51,14 @@ parseInput = Promise.method(function(params, options) { return [appName, options.build, source, image]; }); -renderProgress = function(percentage, stepCount) { - var _, bar, barCount, spaceCount; - if (stepCount == null) { - stepCount = 50; - } - _ = require('lodash'); - percentage = Math.max(0, Math.min(percentage, 100)); - barCount = Math.floor(stepCount * percentage / 100); - spaceCount = stepCount - barCount; - bar = "[" + (_.repeat('=', barCount)) + ">" + (_.repeat(' ', spaceCount)) + "]"; - return bar + " " + (percentage.toFixed(1)) + "%"; -}; - -showPushProgress = function(logStreams) { - var logging; - logging = require('../utils/logging'); - return logging.logInfo(logStreams, renderProgress(0)); -}; - -updatePushProgress = function(percentage, logStreams) { - var ansiEscapes, logging; - logging = require('../utils/logging'); - ansiEscapes = require('ansi-escapes'); - if (percentage >= 100) { - percentage = 100; - } - process.stdout.write(ansiEscapes.cursorUp(1)); - process.stdout.clearLine(); - process.stdout.cursorTo(0); - return logging.logInfo(logStreams, renderProgress(percentage)); +showPushProgress = function(message) { + var progressBar, visuals; + visuals = require('resin-cli-visuals'); + progressBar = new visuals.Progress(message); + progressBar.update({ + percentage: 0 + }); + return progressBar; }; getBundleInfo = function(options) { @@ -91,19 +69,23 @@ getBundleInfo = function(options) { }); }; -performUpload = function(imageStream, token, username, url, appName, logStreams) { - var progressStream, request, streamWithProgress, uploadRequest, zlib; +performUpload = function(imageStream, token, username, url, appName, logger) { + var progressBar, progressMessage, progressStream, request, streamWithProgress, uploadRequest, zlib; request = require('request'); progressStream = require('progress-stream'); zlib = require('zlib'); - showPushProgress(logStreams); + progressMessage = logger.formatMessage('info', 'Deploying').slice(0, -1); + progressBar = showPushProgress(progressMessage); streamWithProgress = imageStream.pipe(progressStream({ time: 500, length: imageStream.length }, function(arg) { - var percentage; - percentage = arg.percentage; - return updatePushProgress(percentage, logStreams); + var eta, percentage; + percentage = arg.percentage, eta = arg.eta; + return progressBar.update({ + percentage: Math.min(percentage, 100), + eta: eta + }); })); uploadRequest = request.post({ url: getBuilderPushEndpoint(url, username, appName), @@ -117,7 +99,7 @@ performUpload = function(imageStream, token, username, url, appName, logStreams) level: 6 })) }); - return uploadToPromise(uploadRequest, logStreams); + return uploadToPromise(uploadRequest, logger); }; uploadLogs = function(logs, token, url, buildId, username, appName) { @@ -133,20 +115,18 @@ uploadLogs = function(logs, token, url, buildId, username, appName) { }); }; -uploadToPromise = function(uploadRequest, logStreams) { - var logging; - logging = require('../utils/logging'); +uploadToPromise = function(uploadRequest, logger) { return new Promise(function(resolve, reject) { var handleMessage; handleMessage = function(data) { var e, obj; data = data.toString(); - logging.logDebug(logStreams, "Received data: " + data); + logger.logDebug("Received data: " + data); try { obj = JSON.parse(data); } catch (error) { e = error; - logging.logError(logStreams, 'Error parsing reply from remote side'); + logger.logError('Error parsing reply from remote side'); reject(e); return; } @@ -157,7 +137,7 @@ uploadToPromise = function(uploadRequest, logStreams) { case 'success': return resolve(obj); case 'status': - return logging.logInfo(logStreams, "Remote: " + obj.message); + return logger.logInfo("Remote: " + obj.message); default: return reject(new Error("Received unexpected reply from remote: " + data)); } @@ -192,13 +172,13 @@ module.exports = { } ]), action: function(params, options, done) { - var _, logStreams, logging, logs, resin, tmp, tmpNameAsync, upload; + var Logger, _, logger, logs, resin, tmp, tmpNameAsync, upload; _ = require('lodash'); tmp = require('tmp'); tmpNameAsync = Promise.promisify(tmp.tmpName); resin = require('resin-sdk-preconfigured'); - logging = require('../utils/logging'); - logStreams = logging.getLogStreams(); + Logger = require('../utils/logger'); + logger = new Logger(); tmp.setGracefulCleanup(); logs = ''; upload = function(token, username, url) { @@ -215,7 +195,7 @@ module.exports = { }); return Promise["try"](function() { if (build) { - return dockerUtils.runBuild(params, options, getBundleInfo, logStreams); + return dockerUtils.runBuild(params, options, getBundleInfo, logger); } else { return { image: imageName, @@ -225,9 +205,9 @@ module.exports = { }).then(function(arg1) { var buildLogs, imageName; imageName = arg1.image, buildLogs = arg1.log; - logging.logInfo(logStreams, 'Initializing deploy...'); + logger.logInfo('Initializing deploy...'); logs = buildLogs; - return Promise.all([dockerUtils.bufferImage(docker, imageName, bufferFile), token, username, url, params.appName, logStreams]).spread(performUpload); + return Promise.all([dockerUtils.bufferImage(docker, imageName, bufferFile), token, username, url, params.appName, logger]).spread(performUpload); })["finally"](function() { return Promise["try"](function() { return require('mz/fs').unlink(bufferFile); @@ -237,7 +217,7 @@ module.exports = { }).tap(function(arg) { var buildId, imageName; imageName = arg.image, buildId = arg.buildId; - logging.logSuccess(logStreams, "Successfully deployed image: " + (formatImageName(imageName))); + logger.logSuccess("Successfully deployed image: " + (formatImageName(imageName))); return buildId; }).then(function(arg) { var buildId, imageName; @@ -245,11 +225,11 @@ module.exports = { if (logs === '' || (options.nologupload != null)) { return ''; } - logging.logInfo(logStreams, 'Uploading logs to dashboard...'); + logger.logInfo('Uploading logs to dashboard...'); return Promise.join(logs, token, url, buildId, username, params.appName, uploadLogs)["return"]('Successfully uploaded logs'); }).then(function(msg) { if (msg !== '') { - return logging.logSuccess(logStreams, msg); + return logger.logSuccess(msg); } }).asCallback(done); }); diff --git a/build/utils/docker.js b/build/utils/docker.js index beef09de..ba9c0b4f 100644 --- a/build/utils/docker.js +++ b/build/utils/docker.js @@ -171,8 +171,8 @@ parseBuildArgs = function(args, onError) { return buildArgs; }; -exports.runBuild = function(params, options, getBundleInfo, logStreams) { - var Promise, dockerBuild, doodles, es, logging, logs, path, qemuPath, resolver, transpose; +exports.runBuild = function(params, options, getBundleInfo, logger) { + var Promise, dockerBuild, doodles, es, logs, path, qemuPath, resolver, transpose; Promise = require('bluebird'); dockerBuild = require('resin-docker-build'); resolver = require('resin-bundle-resolve'); @@ -180,7 +180,6 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) { doodles = require('resin-doodles'); transpose = require('docker-qemu-transpose'); path = require('path'); - logging = require('../utils/logging'); if (params.source == null) { params.source = '.'; } @@ -192,7 +191,7 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) { } return hasQemu().then(function(present) { if (!present) { - logging.logInfo(logStreams, 'Installing qemu for ARM emulation...'); + logger.logInfo('Installing qemu for ARM emulation...'); return installQemu(); } }).then(function() { @@ -224,18 +223,18 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) { buildStream: function(stream) { var buildThroughStream, logThroughStream, newStream; if (options.emulated) { - logging.logInfo(logStreams, 'Running emulated build'); + logger.logInfo('Running emulated build'); } getBundleInfo(options).then(function(info) { var arch, bundle, deviceType; if (info == null) { - logging.logWarn(logStreams, 'Warning: No architecture/device type or application information provided.\n Dockerfile/project pre-processing will not be performed.'); + logger.logWarn('Warning: No architecture/device type or application information provided.\n Dockerfile/project pre-processing will not be performed.'); return tarStream; } else { arch = info[0], deviceType = info[1]; bundle = new resolver.Bundle(tarStream, deviceType, arch); return resolver.resolveBundle(bundle, resolver.getDefaultResolvers()).then(function(resolved) { - logging.logInfo(logStreams, "Building " + resolved.projectType + " project"); + logger.logInfo("Building " + resolved.projectType + " project"); return resolved.tarStream; }); } @@ -264,13 +263,13 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) { } else { newStream = stream; } - return newStream.pipe(logThroughStream).pipe(cacheHighlightStream()).pipe(logStreams.build); + return newStream.pipe(logThroughStream).pipe(cacheHighlightStream()).pipe(logger.streams.build); } }; return generateConnectOpts(options).then(function(connectOpts) { var builder, opts; - logging.logDebug(logStreams, 'Connecting with the following options:'); - logging.logDebug(logStreams, JSON.stringify(connectOpts, null, ' ')); + logger.logDebug('Connecting with the following options:'); + logger.logDebug(JSON.stringify(connectOpts, null, ' ')); builder = new dockerBuild.Builder(connectOpts); opts = {}; if (options.tag != null) { @@ -281,7 +280,7 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) { } if (options.buildArg != null) { opts['buildargs'] = parseBuildArgs(options.buildArg, function(arg) { - return logging.logWarn(logStreams, "Could not parse variable: '" + arg + "'"); + return logger.logWarn("Could not parse variable: '" + arg + "'"); }); } if (options.squash != null) { diff --git a/build/utils/logger.js b/build/utils/logger.js new file mode 100644 index 00000000..3470067c --- /dev/null +++ b/build/utils/logger.js @@ -0,0 +1,61 @@ +// Generated by CoffeeScript 1.12.6 +var Logger, eol; + +eol = require('os').EOL; + +module.exports = Logger = (function() { + function Logger() { + var StreamLogger, _, colors, logger; + StreamLogger = require('resin-stream-logger').StreamLogger; + colors = require('colors'); + _ = require('lodash'); + logger = new StreamLogger(); + logger.addPrefix('build', colors.blue('[Build]')); + logger.addPrefix('info', colors.cyan('[Info]')); + logger.addPrefix('debug', colors.magenta('[Debug]')); + logger.addPrefix('success', colors.green('[Success]')); + logger.addPrefix('warn', colors.yellow('[Warn]')); + logger.addPrefix('error', colors.red('[Error]')); + this.streams = { + build: logger.createLogStream('build'), + info: logger.createLogStream('info'), + debug: logger.createLogStream('debug'), + success: logger.createLogStream('success'), + warn: logger.createLogStream('warn'), + error: logger.createLogStream('error') + }; + _.mapKeys(this.streams, function(stream, key) { + if (key !== 'debug') { + return stream.pipe(process.stdout); + } else { + if (process.env.DEBUG != null) { + return stream.pipe(process.stdout); + } + } + }); + this.formatMessage = logger.formatWithPrefix.bind(logger); + } + + Logger.prototype.logInfo = function(msg) { + return this.streams.info.write(msg + eol); + }; + + Logger.prototype.logDebug = function(msg) { + return this.streams.debug.write(msg + eol); + }; + + Logger.prototype.logSuccess = function(msg) { + return this.streams.success.write(msg + eol); + }; + + Logger.prototype.logWarn = function(msg) { + return this.streams.warn.write(msg + eol); + }; + + Logger.prototype.logError = function(msg) { + return this.streams.error.write(msg + eol); + }; + + return Logger; + +})(); diff --git a/lib/actions/build.coffee b/lib/actions/build.coffee index c0a355fe..4bc6bba6 100644 --- a/lib/actions/build.coffee +++ b/lib/actions/build.coffee @@ -58,7 +58,7 @@ module.exports = }, ] action: (params, options, done) -> - logging = require('../utils/logging') - dockerUtils.runBuild(params, options, getBundleInfo, logging.getLogStreams()) + Logger = require('../utils/logger') + dockerUtils.runBuild(params, options, getBundleInfo, new Logger()) .asCallback(done) diff --git a/lib/actions/deploy.coffee b/lib/actions/deploy.coffee index 77eb10c9..1408ff6d 100644 --- a/lib/actions/deploy.coffee +++ b/lib/actions/deploy.coffee @@ -31,30 +31,11 @@ parseInput = Promise.method (params, options) -> return [appName, options.build, source, image] -# Builds and returns a Docker-like progress bar like this: -# [==================================> ] 64% -renderProgress = (percentage, stepCount = 50) -> - _ = require('lodash') - percentage = Math.max(0, Math.min(percentage, 100)) - barCount = stepCount * percentage // 100 - spaceCount = stepCount - barCount - bar = "[#{_.repeat('=', barCount)}>#{_.repeat(' ', spaceCount)}]" - return "#{bar} #{percentage.toFixed(1)}%" - -showPushProgress = (logStreams) -> - logging = require('../utils/logging') - logging.logInfo(logStreams, renderProgress(0)) - -updatePushProgress = (percentage, logStreams) -> - logging = require('../utils/logging') - ansiEscapes = require('ansi-escapes') - - if percentage >= 100 - percentage = 100 - process.stdout.write(ansiEscapes.cursorUp(1)) - process.stdout.clearLine() - process.stdout.cursorTo(0) - logging.logInfo(logStreams, renderProgress(percentage)) +showPushProgress = (message) -> + visuals = require('resin-cli-visuals') + progressBar = new visuals.Progress(message) + progressBar.update({ percentage: 0 }) + return progressBar getBundleInfo = (options) -> helpers = require('../utils/helpers') @@ -63,16 +44,21 @@ getBundleInfo = (options) -> .then (app) -> [app.arch, app.device_type] -performUpload = (imageStream, token, username, url, appName, logStreams) -> +performUpload = (imageStream, token, username, url, appName, logger) -> request = require('request') progressStream = require('progress-stream') zlib = require('zlib') - showPushProgress(logStreams) - streamWithProgress = imageStream.pipe(progressStream({ + # Need to strip off the newline + progressMessage = logger.formatMessage('info', 'Deploying').slice(0, -1) + progressBar = showPushProgress(progressMessage) + streamWithProgress = imageStream.pipe progressStream time: 500, length: imageStream.length - }, ({ percentage }) -> updatePushProgress(percentage, logStreams))) + , ({ percentage, eta }) -> + progressBar.update + percentage: Math.min(percentage, 100) + eta: eta uploadRequest = request.post url: getBuilderPushEndpoint(url, username, appName) @@ -84,7 +70,7 @@ performUpload = (imageStream, token, username, url, appName, logStreams) -> level: 6 })) - uploadToPromise(uploadRequest, logStreams) + uploadToPromise(uploadRequest, logger) uploadLogs = (logs, token, url, buildId, username, appName) -> request = require('request') @@ -95,19 +81,17 @@ uploadLogs = (logs, token, url, buildId, username, appName) -> bearer: token body: Buffer.from(logs) -uploadToPromise = (uploadRequest, logStreams) -> - logging = require('../utils/logging') - +uploadToPromise = (uploadRequest, logger) -> new Promise (resolve, reject) -> handleMessage = (data) -> data = data.toString() - logging.logDebug(logStreams, "Received data: #{data}") + logger.logDebug("Received data: #{data}") try obj = JSON.parse(data) catch e - logging.logError(logStreams, 'Error parsing reply from remote side') + logger.logError('Error parsing reply from remote side') reject(e) return @@ -115,7 +99,7 @@ uploadToPromise = (uploadRequest, logStreams) -> switch obj.type when 'error' then reject(new Error("Remote error: #{obj.error}")) when 'success' then resolve(obj) - when 'status' then logging.logInfo(logStreams, "Remote: #{obj.message}") + when 'status' then logger.logInfo("Remote: #{obj.message}") else reject(new Error("Received unexpected reply from remote: #{data}")) else reject(new Error("Received unexpected reply from remote: #{data}")) @@ -165,9 +149,8 @@ module.exports = tmpNameAsync = Promise.promisify(tmp.tmpName) resin = require('resin-sdk-preconfigured') - logging = require('../utils/logging') - - logStreams = logging.getLogStreams() + Logger = require('../utils/logger') + logger = new Logger() # Ensure the tmp files gets deleted tmp.setGracefulCleanup() @@ -189,11 +172,11 @@ module.exports = Promise.try -> if build - dockerUtils.runBuild(params, options, getBundleInfo, logStreams) + dockerUtils.runBuild(params, options, getBundleInfo, logger) else { image: imageName, log: '' } .then ({ image: imageName, log: buildLogs }) -> - logging.logInfo(logStreams, 'Initializing deploy...') + logger.logInfo('Initializing deploy...') logs = buildLogs Promise.all [ @@ -202,7 +185,7 @@ module.exports = username url params.appName - logStreams + logger ] .spread(performUpload) .finally -> @@ -213,13 +196,13 @@ module.exports = require('mz/fs').unlink(bufferFile) .catch(_.noop) .tap ({ image: imageName, buildId }) -> - logging.logSuccess(logStreams, "Successfully deployed image: #{formatImageName(imageName)}") + logger.logSuccess("Successfully deployed image: #{formatImageName(imageName)}") return buildId .then ({ image: imageName, buildId }) -> if logs is '' or options.nologupload? return '' - logging.logInfo(logStreams, 'Uploading logs to dashboard...') + logger.logInfo('Uploading logs to dashboard...') Promise.join( logs @@ -232,7 +215,7 @@ module.exports = ) .return('Successfully uploaded logs') .then (msg) -> - logging.logSuccess(logStreams, msg) if msg isnt '' + logger.logSuccess(msg) if msg isnt '' .asCallback(done) Promise.join( diff --git a/lib/utils/docker.coffee b/lib/utils/docker.coffee index 8f246f0e..2f8c8391 100644 --- a/lib/utils/docker.coffee +++ b/lib/utils/docker.coffee @@ -174,7 +174,7 @@ parseBuildArgs = (args, onError) -> # Pass in the command line parameters and options and also # a function which will return the information about the bundle -exports.runBuild = (params, options, getBundleInfo, logStreams) -> +exports.runBuild = (params, options, getBundleInfo, logger) -> Promise = require('bluebird') dockerBuild = require('resin-docker-build') @@ -184,8 +184,6 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) -> transpose = require('docker-qemu-transpose') path = require('path') - logging = require('../utils/logging') - # The default build context is the current directory params.source ?= '.' logs = '' @@ -198,7 +196,7 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) -> hasQemu() .then (present) -> if !present - logging.logInfo(logStreams, 'Installing qemu for ARM emulation...') + logger.logInfo('Installing qemu for ARM emulation...') installQemu() .then -> # Copy the qemu binary into the build context @@ -226,12 +224,12 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) -> buildFailure: reject buildStream: (stream) -> if options.emulated - logging.logInfo(logStreams, 'Running emulated build') + logger.logInfo('Running emulated build') getBundleInfo(options) .then (info) -> if !info? - logging.logWarn logStreams, ''' + logger.logWarn ''' Warning: No architecture/device type or application information provided. Dockerfile/project pre-processing will not be performed. ''' @@ -242,7 +240,7 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) -> bundle = new resolver.Bundle(tarStream, deviceType, arch) resolver.resolveBundle(bundle, resolver.getDefaultResolvers()) .then (resolved) -> - logging.logInfo(logStreams, "Building #{resolved.projectType} project") + logger.logInfo("Building #{resolved.projectType} project") return resolved.tarStream .then (buildStream) -> @@ -275,15 +273,15 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) -> newStream .pipe(logThroughStream) .pipe(cacheHighlightStream()) - .pipe(logStreams.build) + .pipe(logger.streams.build) # Create a builder generateConnectOpts(options) .then (connectOpts) -> # Allow degugging output, hidden behind an env var - logging.logDebug(logStreams, 'Connecting with the following options:') - logging.logDebug(logStreams, JSON.stringify(connectOpts, null, ' ')) + logger.logDebug('Connecting with the following options:') + logger.logDebug(JSON.stringify(connectOpts, null, ' ')) builder = new dockerBuild.Builder(connectOpts) opts = {} @@ -294,7 +292,7 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) -> opts['nocache'] = true if options.buildArg? opts['buildargs'] = parseBuildArgs options.buildArg, (arg) -> - logging.logWarn(logStreams, "Could not parse variable: '#{arg}'") + logger.logWarn("Could not parse variable: '#{arg}'") if options.squash? opts['squash'] = true diff --git a/lib/utils/logger.coffee b/lib/utils/logger.coffee new file mode 100644 index 00000000..d9de3312 --- /dev/null +++ b/lib/utils/logger.coffee @@ -0,0 +1,46 @@ +eol = require('os').EOL + +module.exports = class Logger + constructor: -> + { StreamLogger } = require('resin-stream-logger') + colors = require('colors') + _ = require('lodash') + + logger = new StreamLogger() + logger.addPrefix('build', colors.blue('[Build]')) + logger.addPrefix('info', colors.cyan('[Info]')) + logger.addPrefix('debug', colors.magenta('[Debug]')) + logger.addPrefix('success', colors.green('[Success]')) + logger.addPrefix('warn', colors.yellow('[Warn]')) + logger.addPrefix('error', colors.red('[Error]')) + + @streams = + build: logger.createLogStream('build'), + info: logger.createLogStream('info'), + debug: logger.createLogStream('debug'), + success: logger.createLogStream('success'), + warn: logger.createLogStream('warn'), + error: logger.createLogStream('error') + + _.mapKeys @streams, (stream, key) -> + if key isnt 'debug' + stream.pipe(process.stdout) + else + stream.pipe(process.stdout) if process.env.DEBUG? + + @formatMessage = logger.formatWithPrefix.bind(logger) + + logInfo: (msg) -> + @streams.info.write(msg + eol) + + logDebug: (msg) -> + @streams.debug.write(msg + eol) + + logSuccess: (msg) -> + @streams.success.write(msg + eol) + + logWarn: (msg) -> + @streams.warn.write(msg + eol) + + logError: (msg) -> + @streams.error.write(msg + eol) diff --git a/lib/utils/logging.coffee b/lib/utils/logging.coffee deleted file mode 100644 index 271e8e22..00000000 --- a/lib/utils/logging.coffee +++ /dev/null @@ -1,45 +0,0 @@ -eol = require('os').EOL - -exports.getLogStreams = -> - { StreamLogger } = require('resin-stream-logger') - colors = require('colors') - _ = require('lodash') - - logger = new StreamLogger() - logger.addPrefix('build', colors.blue('[Build]')) - logger.addPrefix('info', colors.cyan('[Info]')) - logger.addPrefix('debug', colors.magenta('[Debug]')) - logger.addPrefix('success', colors.green('[Success]')) - logger.addPrefix('warn', colors.yellow('[Warn]')) - logger.addPrefix('error', colors.red('[Error]')) - - streams = - build: logger.createLogStream('build'), - info: logger.createLogStream('info'), - debug: logger.createLogStream('debug'), - success: logger.createLogStream('success'), - warn: logger.createLogStream('warn'), - error: logger.createLogStream('error') - - _.mapKeys streams, (stream, key) -> - if key isnt 'debug' - stream.pipe(process.stdout) - else - stream.pipe(process.stdout) if process.env.DEBUG? - - streams - -exports.logInfo = (logStreams, msg) -> - logStreams.info.write(msg + eol) - -exports.logDebug = (logStreams, msg) -> - logStreams.debug.write(msg + eol) - -exports.logSuccess = (logStreams, msg) -> - logStreams.success.write(msg + eol) - -exports.logWarn = (logStreams, msg) -> - logStreams.warn.write(msg + eol) - -exports.logError = (logStreams, msg) -> - logStreams.error.write(msg + eol)