Disable installing dependencies for injected packages

--- build/tasks/install-unpublished-packages.coffee
+++ build/tasks/install-unpublished-packages.coffee
@@ -29,11 +29,8 @@
       packages = JSON.parse(fs.readFileSync(packageJson))
       packages.readme = 'ERROR: No README data found!'
       fs.writeFileSync(packageJson, JSON.stringify(packages, null, '  '))
+      callback()

-      options =
-        cwd: path.join(workDir, 'node_modules', name)
-      cp.safeExec 'npm install', options, ->
-        callback()
   r.on 'error', (err) ->
     console.log 'Error while fetching package:', err


Refactor data-driven load tests

Refactor data-driven load tests

--- test/load.coffee
+++ test/load.coffee
@@ -1,117 +1,84 @@
 should = require 'should'
 logger = require 'torch'
-uuid = require 'uuid'

-mockery = require './mockery'
-bus = require '../lib/bus'
-core = require '../lib/core'
+core = require '..'

-describe 'load', ->
+describe 'core.load', ->
   afterEach ->
-    #mockery.disable()
     core.reset()

-  beforeEach ->
-    #mockery.enable()
-    #core.init()

-#   tests = [
-#       description: 'a default base'
-#       module:
-#         name: 'server'
-#         services:
-#           run: (args, done) ->
-#             done null, {status: "success"}
-#       input:
-#         channel: 'server.run'
-#       output:
-#         channel: 'server.run'
-#         topic: 'success.#'
-#         data: {status: "success"}
-#     ,
-#       description: 'a referenced base'
-#       module:
-#         name: 'server'
-#         config:
-#           run:
-#             base: 'lifecycle'
-#             foo: 1
-#             bar: 2
-#       input:
-#         channel: 'server.run'
-#         data: {baz: 45}
-#       output:
-#         channel: 'base.lifecycle'
-#         topic: 'request.#'
-#         data:
-#           args:
-#             {baz: 45}
-#           config:
-#             base: 'lifecycle'
-#             foo: 1
-#             bar: 2
-#     ,
-#       description: 'a law service'
-#       module:
-#         name: 'server'
-#         services:
-#           run:
-#             service: (args, done) ->
-#               done null, {status: "success"}
-#       input:
-#         channel: 'server.run'
-#         data: {foo: 1, bar: 2}
-#       output:
-#         channel: 'server.run'
-#         topic: 'success.#'
-#         data: {status: "success"}
-#     ,
-#       description: 'an aliased namespace'
-#       module:
-#         name: 'implementation'
-#         config:
-#           run:
-#             extends: 'server'
-#         services:
-#           "run/prepare": (args, done) ->
-#             done null, {status: "prepared"}
-#       input:
-#         channel: 'server.run/prepare'
-#         data: {}
-#       output:
-#         channel: 'server.run/prepare'
-#         topic: 'success.#'
-#         data: {status: "prepared"}
-#   ]
+  it 'should load a default base', (done) ->
+    module =
+      services:
+        run: (args, done) ->
+          done null, {status: 'success'}

-#   for test in tests
-#     do (test) ->
-#       {description, module, input, output} = test
-#       it description, (done) ->
-#         core.load module.name, module
+    core.load 'server', module
+    core.request 'server.run', {}, (err, data) ->
+      should.not.exist err
+      should.exist data
+      data.should.eql {status: 'success'}

-#         id = uuid.v1()
+      done()

-#         replyTo =
-#           channel: input.channel
-#           topic:
-#             success: "success.#{id}"
-#             error: "error.#{id}"

-#         bus.subscribe
-#           channel: output.channel
-#           topic: output.topic
-#           callback: (result) ->
-#             should.exist result
-#             result.should.include output.data
-#             done()
+  it 'should load a referenced base', (done) ->
+    core.load 'base', {
+      services:
+        lifecycle: (args, done) ->
+          done null, args.args
+    }

-#         bus.publish
-#           channel: input.channel
-#           topic: "request.#{id}"
-#           data: input.data
-#           replyTo: replyTo
+    core.load 'server', {
+      config:
+        run:
+          base: 'lifecycle'
+    }
+
+    data = {x: 111}
+    core.request 'server.run', data, (err, result) ->
+      should.not.exist err
+      should.exist result
+      result.should.eql data
+
+      done()
+
+
+  it 'should load a law service', (done) ->
+    module =
+      services:
+        run:
+          service: (args, done) ->
+            done null, {status: 'success'}
+
+    core.load 'server', module
+    core.request 'server.run', {}, (err, data) ->
+      should.not.exist err
+      should.exist data
+      data.should.eql {status: 'success'}
+
+      done()
+
+
+  it 'should load an aliased namespace', (done) ->
+    module =
+      config:
+        run:
+          extends: 'server'
+      services:
+        'run/prepare': (args, done) ->
+          done null, {status: 'prepared'}
+
+    core.load 'extension', module
+    core.request 'server.run/prepare', {}, (err, data) ->
+      should.not.exist err
+      should.exist data
+      data.should.eql {status: 'prepared'}
+
+      done()
+

   it 'should receive config in context', (done) ->
     robot =


:lipstick: normalize code structure

:lipstick: normalize code structure

--- test/test.coffee
+++ test/test.coffee
@@ -5,24 +5,23 @@

 test_template_path = path.resolve(_path, '../../')
 test_path          = path.join(_path, 'tmp')
-tpl = 'test-sprout-roots-base'
+tpl                = 'test-sprout-roots-base'
 opts =
   config: path.join(_path, 'locals.json')

 before (done) ->
+  console.log test_template_path
   sprout.add(tpl, test_template_path)
-  .then -> rimraf.sync(test_path)
-  .then -> sprout.init(tpl, test_path, opts)
-  .then -> h.project.install_dependencies('*', done)
+    .then -> rimraf.sync(test_path)
+    .then -> sprout.init(tpl, test_path, opts)
+    .then -> h.project.install_dependencies('*', done)

-after ->
-  sprout.remove(tpl)
+after -> sprout.remove(tpl)

 describe 'sprout', ->
   it 'inits the project properly', (done) ->
     if fs.existsSync(path.join(test_path, 'views'))
       tgt = path.join(test_path, 'views/index.jade')
-
     else
       tgt = path.join(test_path, 'index.jade')


Add test

Add test

--- test/type.coffee
+++ test/type.coffee
@@ -137,3 +137,10 @@
           y :: String = (f 3)
         """

+    test 'typed array', ->
+      struct Point {
+        x :: Number
+        y :: Number
+      }
+      p :: Point = {x: 3, y: 2}
+      tarr :: Point[]  = [{x : 3, y: 3}, {x : 3, y: 3}, p]


Fix consolidation behavior when deleting the first or last character in a block and optimize for removing text from a single block

--- src/trix/models/document.coffee
+++ src/trix/models/document.coffee
@@ -53,11 +53,14 @@

   removeTextAtLocationRange: edit (locationRange) ->
     return if locationRange.isCollapsed()
-    range = @rangeFromLocationRange(locationRange)
-    blockList = @blockList.removeObjectsInRange(range)
-
-    if blockList.length
-      unless @locationRangeEndsAtEndOfBlock(locationRange)
+    if locationRange.isInSingleIndex()
+      @blockList = @blockList.editObjectAtIndex locationRange.index, (block) ->
+        block.copyWithText(block.text.removeTextAtRange([locationRange.start.offset, locationRange.end.offset]))
+    else
+      range = @rangeFromLocationRange(locationRange)
+      blockList = @blockList.removeObjectsInRange(range)
+
+      if blockList.length
         leftIndex = locationRange.index
         rightIndex = leftIndex + 1
         leftBlock = blockList.getObjectAtIndex(leftIndex)
@@ -67,10 +70,8 @@
           blockList = blockList.
             removeObjectAtIndex(rightIndex).
             replaceObjectAtIndex(leftBlock.consolidateWith(rightBlock), leftIndex)
-    else
-      blockList = new Trix.SplittableList [new Trix.Block]
-
-    @blockList = blockList
+
+      @blockList = blockList

   replaceTextAtLocationRange: edit (text, locationRange) ->
     @removeTextAtLocationRange(locationRange)
@@ -228,10 +229,6 @@
         offset = leftOffset
     new Trix.LocationRange {index, offset}

-  locationRangeEndsAtEndOfBlock: (locationRange) ->
-    {offset, index} = locationRange.end
-    offset is @getBlockAtIndex(index).getLength()
-
   toString: ->
     @blockList.toString()


Remove logging

Remove logging

--- src/trix/text_controller.coffee
+++ src/trix/text_controller.coffee
@@ -60,7 +60,6 @@
       @deleteFromCurrentPosition(positionBeforeLastWord - position)

   render: ->
-    console.log "rendering"
     @textView.render()

   # Current attributes


update utils and flow services dependencies

--- static/coffee/flows/services.coffee
+++ static/coffee/flows/services.coffee
@@ -5,7 +5,7 @@
 quietPeriod = 500
 errorRetries = 10

-app.service "utils", ->
+app.service "utils", ['$modal', ($modal) ->

   isWindow = (obj) ->
     obj and obj.document and obj.location and obj.alert and obj.setInterval
@@ -102,6 +102,7 @@
       controller: controller
       resolve: resolveObj

+]
 #============================================================================
 # DragHelper is all kinds of bad. This facilitates the little helper cues
 # for the user so they learn the mechanics of building a flow. We should
@@ -397,7 +398,7 @@

 ]

-app.factory 'Flow', ['$rootScope', '$window', '$http', '$timeout', '$interval', '$log', '$modal', 'utils', 'Plumb', 'Revisions', 'DragHelper', ($rootScope, $window, $http, $timeout, $interval, $log, $modal, utils, Plumb, Revisions, DragHelper) ->
+app.factory 'Flow', ['$rootScope', '$window', '$http', '$timeout', '$interval', '$log', 'utils', 'Plumb', 'Revisions', 'DragHelper', ($rootScope, $window, $http, $timeout, $interval, $log, utils, Plumb, Revisions, DragHelper) ->

   new class Flow


frameless window for transparency

frameless window for transparency


Fix typing over text

Fix typing over text

--- src/trix/models/document.coffee
+++ src/trix/models/document.coffee
@@ -49,6 +49,7 @@
     @insertDocumentAtLocationRange(document, locationRange)

   insertTextAtLocationRange: edit (text, locationRange) ->
+    @removeTextAtLocationRange(locationRange)
     @blockList = @blockList.editObjectAtIndex locationRange.index, (block) ->
       if block.isPlaceholder()
         block.copyWithText(text)
@@ -76,10 +77,6 @@
             replaceObjectAtIndex(leftBlock.consolidateWith(rightBlock), leftIndex)

       @blockList = blockList
-
-  replaceTextAtLocationRange: edit (text, locationRange) ->
-    @removeTextAtLocationRange(locationRange)
-    @insertTextAtLocationRange(text, locationRange)

   moveTextFromLocationRangeToPosition: edit (locationRange, position) ->
     range = @rangeFromLocationRange(locationRange)


Warn when takeWhile(EventStream)

Warn when takeWhile(EventStream)

--- src/takewhile.coffee
+++ src/takewhile.coffee
@@ -1,8 +1,12 @@
 # build-dependencies: observable, filter

 Bacon.Observable :: takeWhile = (f, args...) ->
+  suspiciousUsage = this instanceof Bacon.EventStream
   convertArgsToFunction this, f, args, (f) ->
     withDescription(this, "takeWhile", f, @withHandler (event) ->
+      if suspiciousUsage then console.warn(
+        "Bacon.Observable.takeWhile(EventStream) always returns true. Consider converting the EventStream into Property."
+      )
       if event.filter(f)
         @push event
       else


Remove defaults; add an Array of valid hash fields as a hack around a broken API

--- models/collector_profile.coffee
+++ models/collector_profile.coffee
@@ -9,8 +9,12 @@

   url: "#{API_URL}/api/v1/me/collector_profile"

-  defaults:
-    session_id: SESSION_ID
+  validHashFields: [
+    'owner'
+    'institutional_affiliations'
+    'confirmed_buyer_at'
+    'collector_level'
+  ]

   fetch: (options = {}) ->
     options.data = _.extend options.data or {}, @pick('anonymous_session_id'), session_id: SESSION_ID


status component isn't used any longer

status component isn't used any longer

--- src/user/status.cjsx
+++ src/user/status.cjsx
@@ -1,69 +0,0 @@
-React = require 'react'
-BS = require 'react-bootstrap'
-{CloseButton} = require 'openstax-react-components'
-
-user = require './model'
-api = require '../api'
-
-getWaitingText = (status) ->
-  "#{status}…"
-
-UserStatus = React.createClass
-  displayName: 'UserStatus'
-
-  propTypes:
-    close: React.PropTypes.func
-
-  componentWillMount: ->
-    user.ensureStatusLoaded()
-    user.channel.on("change", @update)
-
-  componentWillUnmount: ->
-    user.channel.off("change", @update)
-
-  update: ->
-    @forceUpdate() if @isMounted()
-
-  showProfile: ->
-    user.channel.emit("show.task", {view: 'task'})
-
-  showProgress: ->
-    user.channel.emit("show.progress", {view: 'dashboard'})
-
-  close: ->
-    @props.close?()
-
-  handleSelect: (selectedKey) ->
-    @[selectedKey]?()
-
-  render: ->
-    status = if user.isLoggedIn() then "logged in as #{user.name}" else 'an unknown user'
-    brand = [
-      Concept
-      'Coach'
-    ]
-    <BS.Navbar brand={brand} fixedTop fluid>
-      <BS.CollapsibleNav eventKey={0}>
-        <BS.Nav navbar>
-        </BS.Nav>
-        <BS.Nav right navbar activeKey={1} onSelect={@handleSelect}>
-          <BS.NavItem
-            eventKey={'showProfile'}
-            className='concept-coach-user'>
-            {user.name}
-          </BS.NavItem>
-          <BS.NavItem
-            eventKey={'showProgress'}
-            className='concept-coach-dashboard-button'>
-            My Progress
-          </BS.NavItem>
-          <BS.NavItem
-            eventKey={'close'}>
-            <CloseButton/>
-          </BS.NavItem>
-        </BS.Nav>
-      </BS.CollapsibleNav>
-    </BS.Navbar>
-
-
-module.exports = UserStatus


Lava code ¬_¬

Lava code ¬_¬

--- src/slide-pack-processor.coffee
+++ src/slide-pack-processor.coffee
@@ -36,18 +36,12 @@
   cssClass : slide.slideClass
   html : markdown.renderJsonML markdown.toHTMLTree(slide)

-fixCodeBlocks = (slide) ->
-  console.log slide
-
-
 slidePackProcessor = do ->

   process = (md) ->
     tree = markdown.parse(md)
     slides = slider md

-    (fixCodeBlocks(slide) for slide in slides)
-
     (generateSlide(slide) for slide in slides)

   process : process


fix https://github.com/sagemathinc/smc/issues/1768 -- "_set_codemirror_to_syncstring → setValueNoJump → diff_main: Error: Null input "

--- src/smc-webapp/misc_page.coffee
+++ src/smc-webapp/misc_page.coffee
@@ -731,6 +731,12 @@
     # Set the value of the buffer to something new by replacing just the ranges
     # that changed, so that the view/history/etc. doesn't get messed up.
     CodeMirror.defineExtension 'setValueNoJump', (value, scroll_last) ->
+        if not value?
+            # Special case -- trying to set to value=undefined.  This is the sort of thing
+            # that might rarely happen right as the document opens or closes, for which
+            # there is no meaningful thing to do but "do nothing".  We detected this periodically
+            # by catching user stacktraces in production...  See https://github.com/sagemathinc/smc/issues/1768
+            return
         r = @getOption('readOnly')
         if not r
             @setOption('readOnly', true)


removed useless disabled line, fixed focus input

--- src/smc-webapp/project_new.cjsx
+++ src/smc-webapp/project_new.cjsx
@@ -220,6 +220,10 @@
         if newProps.default_filename != @props.default_filename
             @setState(filename: newProps.default_filename)

+    componentDidUpdate: ->
+        if not @state.warning
+            ReactDOM.findDOMNode(@refs.project_new_filename).focus()
+
     default_filename : ->
         return require('./account').default_filename()

@@ -239,7 +243,7 @@
         e.preventDefault()
         if @state.filename[@state.filename.length - 1] == '/'
             @create_folder()
-        else if ReactDOM.findDOMNode(@refs.project_new_filename).value.includes('.')
+        else if @state.filename.includes(".")
             @create_file()
         else
             @setState(warning : true)
@@ -274,11 +278,6 @@
             on_error     : on_error
             switch_over  : true

-    decline_file : ->
-        @setState(warning : false)
-        ReactDOM.findDOMNode(@refs.project_new_filename).disabled = false
-        ReactDOM.findDOMNode(@refs.project_new_filename).focus()
-
     render_alert : ->
         <Alert bsStyle='warning' style={marginTop: '10px', fontWeight : 'bold'}>

Warning: Are you sure you want to create a file with no extensions?

@@ -286,7 +285,7 @@
                 <Button onClick={=>@create_file()} bsStyle='success'>
                     Create file
                 </Button>
-                <Button onClick={@decline_file} bsStyle='default'>
+                <Button onClick={=>@setState(warning : false)} bsStyle='default'>
                     Cancel
                 </Button>
             </ButtonToolbar>


much faster demo generating data in the script


Fix root_route references in server

Fix root_route references in server

--- src/streammachine/server.coffee
+++ src/streammachine/server.coffee
@@ -28,11 +28,11 @@
         # default URL (and also a mapping for weird stream.nsv route)
         if @core.root_route && (req.url == '/' || req.url == "/;stream.nsv")
             # pretend the request came in on the default stream
-            req.url = "/#{@root_route}"
+            req.url = "/#{@core.root_route}"

         # default playlist
         if @core.root_route && req.url == "/listen.pls"
-            req.url = "/#{@root_route}.pls"
+            req.url = "/#{@core.root_route}.pls"

         # -- utility routes -- #


Log document id with edit operations

Log document id with edit operations

--- src/trix/models/document.coffee
+++ src/trix/models/document.coffee
@@ -48,7 +48,7 @@
   beginEditing: ->
     if @editDepth++ is 0
       @editCount++
-      console.group("Edit operation #{@editCount}")
+      console.group("Document #{@id}: Edit operation #{@editCount}")
       console.groupCollapsed("Backtrace")
       console.trace()
       console.groupEnd()


fix silent syntax error on latest jquery

--- vendor/assets/javascripts/twitter/bootstrap/rails/confirm.coffee
+++ vendor/assets/javascripts/twitter/bootstrap/rails/confirm.coffee
@@ -7,13 +7,15 @@
       proceed_class: "btn proceed btn-primary"

   TwitterBootstrapConfirmBox = (message, element, callback) ->
-    $(document.body).append($('
-

-
<button type="button" class="close" data-dismiss="modal">×</button>
...

-

-
......

-

-    '))
+    $(document.body).append(
+      $(
+        '

+
<button type="button" class="close" data-dismiss="modal">×</button>
...

+

+
......

+
'
+      )
+    )

     $("#confirmation_dialog .modal-body").html(message)
     $("#confirmation_dialog .modal-header h3").html(element.data("confirm-title") || $.fn.twitter_bootstrap_confirmbox.defaults.title || window.top.location.origin)


simplification

simplification

--- src/djinn.coffee
+++ src/djinn.coffee
@@ -42,10 +42,9 @@
       tip = thing[1]
       path = [tip.val]
       t = null
-      while (t = tip.parent)
-        if t.val
-          path.unshift(t.val)
-        tip = t
+      while (tip = tip.parent)
+        if tip.val
+          path.unshift(tip.val)
       match = [path, state.finalValue]
   match


Remove unused QUnit callbacks

Remove unused QUnit callbacks

--- test/src/sauce_labs_reporter.coffee
+++ test/src/sauce_labs_reporter.coffee
@@ -1,10 +0,0 @@
-window.global_test_results = {}
-failures = []
-
-QUnit.testStart (testDetails) ->
-  QUnit.log (details) ->
-    failures.push(details) unless details.result
-
-QUnit.done (results) ->
-  results.failures = failures
-  window.global_test_results = results


:bug: Fix typo in forms widget

:bug: Fix typo in forms widget

--- src/widgets/widgets/form.coffee
+++ src/widgets/widgets/form.coffee
@@ -15,7 +15,7 @@
   fields = document.querySelectorAll(queryFields)
   actions = document.querySelectorAll(queryActions)

-  Array::forEaxch.call fields, (field) ->
+  Array::forEach.call fields, (field) ->
     # TODO create a field object for each input

   Array::forEach.call actions, (trigger) ->


separated layers.on tests for better results

--- testSpecApp/app/specs/layers.coffee
+++ testSpecApp/app/specs/layers.coffee
@@ -2,7 +2,7 @@

   beforeEach (done) ->
     document.addEventListener "deviceready", ->
-      setTimeout done, 500
+      setTimeout done, 750
       # to solve iOS issue of trying to push when previous push is still under way

   it "should be defined", ->
@@ -27,13 +27,37 @@
           done new Error "could not push view: " + error.message
       }

+
   describe "layers.on", ->
-    it "should log 4 layer events in total when pushing and popping a layer", (done)->
+    it "should log 2 'willchange' events when pushing & popping a layer", (done)->

       eventsCount = 0

       steroids.layers.on "willchange", ->
         eventsCount++
+
+      googleView = new steroids.views.WebView "http://www.google.com"
+
+      steroids.layers.push {
+        view: googleView
+      }, {
+        onSuccess: ->
+          setTimeout ->
+            steroids.layers.pop {},
+              onSuccess: ->
+                eventsCount.should.equal 2
+                done()
+              onFailure: (error) ->
+                done new Error "could not pop view: " + error.message
+          , 500
+        onFailure: (error) ->
+          done new Error "could not push view: " + error.message
+      }
+
+
+    it "should log 2 'didchange' events when pushing & popping a layer", (done)->
+
+      eventsCount = 0

       steroids.layers.on "didchange", ->
         eventsCount++
@@ -47,11 +71,12 @@
           setTimeout ->
             steroids.layers.pop {},
               onSuccess: ->
-                eventsCount.should.equal 4
+                eventsCount.should.equal 2
                 done()
               onFailure: (error) ->
                 done new Error "could not pop view: " + error.message
           , 500
         onFailure: (error) ->
           done new Error "could not push view: " + error.message
-      }+      }
+


Turn off auto connection to mongodb server


moving mounting code into index.coffee

moving mounting code into index.coffee

--- src/index.coffee
+++ src/index.coffee
@@ -47,7 +47,8 @@
       root.id = 'exercise'
       document.body.appendChild(root)

-      React.renderComponent(Exercise({config}), root)
+      exercise = window.ExerciseComponent({config})
+      window.React.render(exercise, root)

       # Save on every change
       ExerciseStore.addChangeListener ->
@@ -61,3 +62,36 @@

         ajax options, (err, value) ->
           console.log('Save Response:', arguments...)
+
+
+document.addEventListener('DOMContentLoaded', ->
+  url = prompt('URL to fetch Exercise JSON\n (leave blank to use local test file)',
+    '/api/exercises/1')
+  if (url)
+    request = new XMLHttpRequest()
+    request.open('GET', url, true)
+
+    request.onload = ->
+      if (request.status >= 200 && request.status < 400)
+        data = JSON.parse(request.responseText)
+
+        root = document.getElementById('exercise')
+        exercise = window.ExerciseComponent({config:data})
+        window.React.render(exercise, root)
+
+      else
+        alert('Woops, server returned a non 200 error')
+
+    request.onerror = ->
+      alert('Woops, problem connecting to server')
+
+    request.send()
+
+  else
+    window.ExerciseComponent(document.getElementById('exercise'), window.config)
+    window.ExerciseActionsStore.ExerciseActions.changeExerciseMode(
+      window.ExerciseActionsStore.EXERCISE_MODES.EDIT
+    )
+
+)
+


Perfs : creating 5 jquery objects on each step is too much

--- graphs.coffee
+++ graphs.coffee
@@ -316,18 +316,25 @@
       @animationValues = @values.slice()
       @animationIndices = @indices.slice()
       @redraw()
-
+
+  domStats:
+    swaps: $("#js-swaps")
+    inserts: $("#js-inserts")
+    shifts: $("#js-shifts")
+    compares: $("#js-compares")
+    result: $("#js-result")
+
   playStep: =>
     step = @animationQueue.shift()
     if step?
-      $("#js-swaps").html(step.swaps)
-      $("#js-inserts").html(step.inserts)
-      $("#js-shifts").html(if step.inserts then Math.floor(step.shifts / step.inserts) else 0)
-      $("#js-compares").html(step.compares)
+      @domStats.swaps.html(step.swaps)
+      @domStats.inserts.html(step.inserts)
+      @domStats.shifts.html(if step.inserts then Math.floor(step.shifts / step.inserts) else 0)
+      @domStats.compares.html(step.compares)
       localsString = ""
       for k, v of step.locals
         localsString += "#{k}: #{v}<br />"
-      $("#js-result").html(localsString)
+      @domStats.result.html(localsString)
     if !step? || @stop
       $("#js-stop").hide()
       $("#js-run").show()


koding-dnode-protocol: add a middleware stack parameter

--- node_modules_koding/koding-dnode-protocol/lib/koding-dnode-protocol/index.coffee
+++ node_modules_koding/koding-dnode-protocol/lib/koding-dnode-protocol/index.coffee
@@ -95,7 +95,7 @@
 * @description an implementation of the Scrubber class from dnode-protocol that supports a middleware stack
 ###
 exports.Scrubber = class DnodeScrubber extends Scrubber
-  constructor:(store=new DnodeStore)->
+  constructor:(store=new DnodeStore, stack)->
     @paths = {}
     @links = []
     dnodeMutators = [
@@ -118,7 +118,7 @@
       #       to    : cursor.path
       #     cursor.update '[Circular]', yes
     ]
-    userStack = DnodeScrubber.stack or []
+    userStack = stack ? DnodeScrubber.stack ? []
     Scrubber.apply @, dnodeMutators.concat userStack

   unscrub:(msg, getCallback)->


Pretty well starting clean with Ground class.

--- ground.coffee
+++ ground.coffee
@@ -1,231 +1,237 @@
 MetaHub = require 'metahub'
 Meta_Object = MetaHub.Meta_Object
-Query = require './classes/Query.coffee'
-Trellis = require './classes/Trellis.coffee'
-Database = require './node_modules/ground_db/Ground_Database.coffee'
-Table = require './node_modules/ground_db/Ground_Database.coffee'
-fs = require 'fs'
-
-Property_Type = Meta_Object.subclass 'Property_Type',
-  name: ''
-  property_class: ''
-  field_type: ''
-  'default': null
-  initialize: (name, info, types)->
-    # Transferring parent properties is done before any other assignment
-
-
-    # so the MetaHub::extend() can be overridden.
-    if info.parent
-      parent = types[info.parent]
-      MetaHub.extend(this, parent)
-      @parent = parent
-
-    else
-      @field_type = info.field_type
-
-    @name = name
-    @property_class = 'Bloom_Property'
-    if info['default']
-      this['default'] = info['default']
+Ground_Database = require 'ground_db'
+
+#Query = require './classes/Query.coffee'
+#Trellis = require './classes/Trellis.coffee'
+#Database = require './node_modules/ground_db/Ground_Database.coffee'
+#Table = require './node_modules/ground_db/Ground_Database.coffee'
+#fs = require 'fs'
+
+#Property_Type = Meta_Object.subclass 'Property_Type',
+#  name: ''
+#  property_class: ''
+#  field_type: ''
+#  'default': null
+#  initialize: (name, info, types)->
+#    # Transferring parent properties is done before any other assignment
+#
+#
+#    # so the MetaHub::extend() can be overridden.
+#    if info.parent
+#      parent = types[info.parent]
+#      MetaHub.extend(this, parent)
+#      @parent = parent
+#
+#    else
+#      @field_type = info.field_type
+#
+#    @name = name
+#    @property_class = 'Bloom_Property'
+#    if info['default']
+#      this['default'] = info['default']

 module.exports = Meta_Object.subclass 'Ground',
+
   trellises: []
-  map: []
-  queries: []
-  property_types: []
-  db: ''
-  # Eventually Ground MetaHub will support optimize_getter()
-  modules: []
-  initialize: (database)->
-    if database == undefined
-      database = null
-    if database
-      @db = Ground_Database.create()
-      @connect(database)
-
-    @load_schema_from_file('./vineyard.json')
-    @listen(this, 'connect.query', 'on_connect_query')
-    json = fs.readFileSync('./property_types.json', "ascii")
-    property_types = JSON.parse(json)
-    for name, info of property_types
-      type = Property_Type.create(name, info, @property_types)
-      @property_types[name] = type
-
-  add_module: (name)->
-    module = new name()
-    @connect(module, 'module', 'ground')
-    @modules[name] = module
-
-  on_connect_query: (query)->
-    @listen(query, 'all', 'respond')
-
-  respond: ->
-    args = func_get_args()
-    call_user_func_array([this, 'invoke'], args)
-
-  initialize_trellises: (subset, all)->
-    if all == undefined
-      all = null
-    if all == null
-      all = subset
-
-
-    for object in subset
-      # Convert a string reference into a direct reference to the actual object
-      if object.parent
-        object.parent = all[object.parent]
-        object.check_primary_key()
-
-    for object in subset
-      object.update_core_properties()
-
-  load_schema_from_file: (schema_file)->
-    json = fs.readFileSync(schema_file, "ascii")
-    if json == false
-      throw new Error('Could not find schema file: ' + schema_file)
-
-    data = JSON.parse(json)
-    if !data || typeof data != 'object'
-      throw new Error('Invalid JSON in file $schema_file.')
-
-    @parse_schema(data)
-
-  parse_schema: (data)->
-    if data.trellises
-      @load_trellises(data.trellises)
-
-    if data.tables
-      @load_tables(data.tables)
-
-  load_schema_from_database: ->
-    # The SQL would be a lot simpler except we are converting
-
-
-    # ids to name keys.
-    sql = """
-SELECT trellis.id, trellis.name, trellis.plural, trellis.primary_key, parent_trellis.name as parent
-FROM vineyard_trellises trellis
-LEFT JOIN vineyard_trellises parent_trellis ON trellis.parent = parent_trellis.id
-
-"""
-
-    rows = @query_objects(sql)
-    trellises = []
-    sql = """
-SELECT property.name, property.type, property.readonly,
-property.insert_trellis, other_trellis.name as trellis
-FROM vineyard_properties property
-LEFT JOIN vineyard_trellises other_trellis ON property.trellis = other_trellis.id
-WHERE property.trellis = ?
-
-"""
-
-    for row of rows
-      properties = @query_objects(sql, [row.id])
-      row.properties = []
-      if row.plural
-        delete row.plural
-
-
-      for property of properties
-        row.properties[property.name] = property
-        if property.readonly
-          property.readonly = true
-
-
-        if property.insert_trellis
-          property.insert_trellis = true
-
-
-      trellis = Trellis.create(row.name, this)
-      trellis.load_from_object(row)
-      trellises[row.name] = trellis
-
-    @trellises = MetaHub.extend(@trellises, trellises)
-    @initialize_trellises(trellises, @trellises)
-
-  load_map: (map_file)->
-    json = file_get_contents(map_file)
-    data = json_decode(json)
-    if data.map
-      for key, map of data.map
-        trellis = @trellises[key]
-        if trellis
-          for key, field_name of map.fields
-            property = trellis.all_properties[key]
-            if property
-              property.field_name = field_name
-
-  load_tables: (tables)->
-    for key, object of tables
-      table = Table.create(key, this)
-      table.load_from_schema(object)
-      @tables[key] = table
-
-  load_trellises: (trellises)->
-    for key, object of trellises
-      trellis = Trellis.create(key, this)
-      trellis.load_from_object(object)
-      if trellis.id
-        trellis.id = count(@trellises)
-
-      @trellises[key] = trellis
-
-    @initialize_trellises(@trellises, @trellises)
-
-  create_query: (trellis, include_links)->
-    if include_links == undefined
-      include_links = true
-    if is_string(trellis)
-      if @trellises[trellis]
-        throw Exception.create('Class ' + trellis + ' does not exist')
-
-      trellis = @trellises[trellis]
-
-    for key, query of @queries
-      if trellis.is_a(key)
-        return new query(trellis, include_links)
-
-    return Query.create(trellis, include_links)
-
-  convert_value: (value, type)->
-    if value == null
-      if type == 'bool'
-        return false
-
-      return null
-
-    switch type
-      when 'int'
-        return parseInt(value)
-        break
-      when 'string', 'text', 'reference'
-        return value
-        break
-      when 'bool'
-        return str_to_bool(value)
-        break
-      when 'double'
-        return parseFloat(value)
-        break
-
-    return null
-
-  prepare_for_serialization: ->
-    result = {}
-    result.trellises = []
-    for key, trellis of @trellises
-      result.trellises[key] = trellis.get_data()
-
-    return result
-
-  to_json: ->
-    result = @prepare_for_serialization()
-    return JSON.stringify(result)
-
- module.exports.import_into = (target)->
-   target.MetaHub = MetaHub
-   target.Meta_Object = Meta_Object
-   target.Ground = module.exports
-   target.Property_Type = Property_Type+
+#  map: []
+#  queries: []
+#  property_types: []
+#  db: ''
+#  # Eventually Ground MetaHub will support optimize_getter()
+#  modules: []
+#  initialize: (database)->
+#    if database == undefined
+#      database = null
+#    if database
+#      @db = Ground_Database.create()
+#      @connect(database)
+#
+#    @load_schema_from_file('./vineyard.json')
+#    @listen(this, 'connect.query', 'on_connect_query')
+#    json = fs.readFileSync('./property_types.json', "ascii")
+#    property_types = JSON.parse(json)
+#    for name, info of property_types
+#      type = Property_Type.create(name, info, @property_types)
+#      @property_types[name] = type
+#
+#  add_module: (name)->
+#    module = new name()
+#    @connect(module, 'module', 'ground')
+#    @modules[name] = module
+#
+#  on_connect_query: (query)->
+#    @listen(query, 'all', 'respond')
+#
+#  respond: ->
+#    args = func_get_args()
+#    call_user_func_array([this, 'invoke'], args)
+#
+#  initialize_trellises: (subset, all)->
+#    if all == undefined
+#      all = null
+#    if all == null
+#      all = subset
+#
+#
+#    for object in subset
+#      # Convert a string reference into a direct reference to the actual object
+#      if object.parent
+#        object.parent = all[object.parent]
+#        object.check_primary_key()
+#
+#    for object in subset
+#      object.update_core_properties()
+#
+#  load_schema_from_file: (schema_file)->
+#    json = fs.readFileSync(schema_file, "ascii")
+#    if json == false
+#      throw new Error('Could not find schema file: ' + schema_file)
+#
+#    data = JSON.parse(json)
+#    if !data || typeof data != 'object'
+#      throw new Error('Invalid JSON in file $schema_file.')
+#
+#    @parse_schema(data)
+#
+#  parse_schema: (data)->
+#    if data.trellises
+#      @load_trellises(data.trellises)
+#
+#    if data.tables
+#      @load_tables(data.tables)
+#
+#  load_schema_from_database: ->
+#    # The SQL would be a lot simpler except we are converting
+#
+#
+#    # ids to name keys.
+#    sql = """
+#SELECT trellis.id, trellis.name, trellis.plural, trellis.primary_key, parent_trellis.name as parent
+#FROM vineyard_trellises trellis
+#LEFT JOIN vineyard_trellises parent_trellis ON trellis.parent = parent_trellis.id
+#
+#"""#
+#
+#    rows = @query_objects(sql)
+#    trellises = []
+#    sql = """#
+#SELECT property.name, property.type, property.readonly,
+#property.insert_trellis, other_trellis.name as trellis
+#FROM vineyard_properties property
+#LEFT JOIN vineyard_trellises other_trellis ON property.trellis = other_trellis.id
+#WHERE property.trellis = ?
+
+#"""#
+#
+#    for row of rows
+#      properties = @query_objects(sql, [row.id])
+#      row.properties = []
+#      if row.plural
+#        delete row.plural
+#
+#
+#      for property of properties
+#        row.properties[property.name] = property
+#        if property.readonly
+#          property.readonly = true
+#
+#
+#        if property.insert_trellis
+#          property.insert_trellis = true
+#
+#
+#      trellis = Trellis.create(row.name, this)
+#      trellis.load_from_object(row)
+#      trellises[row.name] = trellis
+#
+#    @trellises = MetaHub.extend(@trellises, trellises)
+#    @initialize_trellises(trellises, @trellises)
+#
+#  load_map: (map_file)->
+#    json = file_get_contents(map_file)
+#    data = json_decode(json)
+#    if data.map
+#      for key, map of data.map
+#        trellis = @trellises[key]
+#        if trellis
+#          for key, field_name of map.fields
+#            property = trellis.all_properties[key]
+#            if property
+#              property.field_name = field_name
+#
+#  load_tables: (tables)->
+#    for key, object of tables
+#      table = Table.create(key, this)
+#      table.load_from_schema(object)
+#      @tables[key] = table
+#
+#  load_trellises: (trellises)->
+#    for key, object of trellises
+#      trellis = Trellis.create(key, this)
+#      trellis.load_from_object(object)
+#      if trellis.id
+#        trellis.id = count(@trellises)
+#
+#      @trellises[key] = trellis
+#
+#    @initialize_trellises(@trellises, @trellises)
+#
+#  create_query: (trellis, include_links)->
+#    if include_links == undefined
+#      include_links = true
+#    if is_string(trellis)
+#      if @trellises[trellis]
+#        throw Exception.create('Class ' + trellis + ' does not exist')
+#
+#      trellis = @trellises[trellis]
+#
+#    for key, query of @queries
+#      if trellis.is_a(key)
+#        return new query(trellis, include_links)
+#
+#    return Query.create(trellis, include_links)
+#
+#  convert_value: (value, type)->
+#    if value == null
+#      if type == 'bool'
+#        return false
+#
+#      return null
+#
+#    switch type
+#      when 'int'
+#        return parseInt(value)
+#        break
+#      when 'string', 'text', 'reference'
+#        return value
+#        break
+#      when 'bool'
+#        return str_to_bool(value)
+#        break
+#      when 'double'
+#        return parseFloat(value)
+#        break
+#
+#    return null
+#
+#  prepare_for_serialization: ->
+#    result = {}
+#    result.trellises = []
+#    for key, trellis of @trellises
+#      result.trellises[key] = trellis.get_data()
+#
+#    return result
+#
+#  to_json: ->
+#    result = @prepare_for_serialization()
+#    return JSON.stringify(result)
+
+# module.exports.import_into = (target)->
+#   target.MetaHub = MetaHub
+#   target.Meta_Object = Meta_Object
+#   target.Ground = module.exports
+#   target.Property_Type = Property_Type
+
+module.exports.Ground_Database = Ground_Database


Rename variable to something more fitting

--- src/robot.coffee
+++ src/robot.coffee
@@ -193,12 +193,12 @@

     @connect.listen process.env.PORT || 8080

-    hostname = process.env.HEROKU_URL
-
-    if hostname
-      hostname += '/' unless /\/$/.test hostname
+    herokuUrl = process.env.HEROKU_URL
+
+    if herokuUrl
+      herokuUrl += '/' unless /\/$/.test herokuUrl
       setInterval =>
-        HttpClient.create("#{hostname}hubot/ping")
+        HttpClient.create("#{herokuUrl}hubot/ping")
           .post() (err, res, body) =>
             @logger.info "keep alive ping!"
       , 1200000


Removing weird methods scraped from mozilla docs

--- src/stubs.coffee
+++ src/stubs.coffee
@@ -282,22 +282,6 @@

-@name small
-@methodOf String#
-###
-###*
-Non-standard
-
-
-
-@name strike
-@methodOf String#
-###
-###*
-Non-standard
-
-
-
 @name sub
 @methodOf String#
 ###


Add update webhook header

Add update webhook header

--- static/coffee/flows/controllers.coffee
+++ static/coffee/flows/controllers.coffee
@@ -1047,7 +1047,7 @@
   if ruleset.config
     formData.webhook = ruleset.config.webhook
     formData.webhook_action = ruleset.config.webhook_action
-    formData.webhook_header = ruleset.config.webhook_header
+    formData.webhook_header = ruleset.config.webhook_header or {}

   formData.rulesetConfig = Flow.getRulesetConfig({type:ruleset.ruleset_type})

@@ -1091,21 +1091,13 @@
   formData.flowField = Flow.getFieldSelection($scope.flowFields, $scope.ruleset.operand, true)
   formData.contactField = Flow.getFieldSelection($scope.contactFields, $scope.ruleset.operand, false)

-  $scope.showAdditionalOptions = () ->
-    if formData.isAdditionalOptionsVisible
-      formData.isAdditionalOptionsVisible = false
-    else
-      formData.isAdditionalOptionsVisible = true
-      if formData.webhook_header.length == 0
-        $scope.addNewWebhookHeader()
-
-  formData.webhook_header = []
-  $scope.addNewWebhookHeader = () ->
-    formData.webhook_header.push
-      key: ''
-      value: ''
-
-  formData.isAdditionalOptionsVisible = false
+  #-----------------------------------------------------------------
+  # Webhook Header
+  #-----------------------------------------------------------------
+
+  $scope.updateWebhookHeader = (key, value) ->
+    if key and value
+      formData.webhook_header[key] = value

   config = $scope.ruleset.config
   if not config


fix info update on ureporters map

fix info update on ureporters map

--- static/coffee/ureporters.coffee
+++ static/coffee/ureporters.coffee
@@ -238,6 +238,11 @@

     if props?
       result = boundaryResults[props.id]
+      if not result
+        result =
+          set:0
+          unset:0
+
       html = "
"
       html += "
" + props.name + "
"


remove logging

remove logging

--- tests/mocha/lib/login-helper.coffee
+++ tests/mocha/lib/login-helper.coffee
@@ -29,7 +29,6 @@
   waitForPasswordResetConfirmation: (email, callback) ->
     LoginHelper.waitForEvent ->
       confirmation = $('div.constrain-copy.push p').text().indexOf "Your password has been reset."
-      console.log $('div.constrain-copy.push p')
       return confirmation > -1
     , callback


Stop frequently render (@setState).

Stop frequently render (@setState).

--- views/index.cjsx
+++ views/index.cjsx
@@ -102,16 +102,19 @@
     {method, path, body, postBody} = e.detail
     {$ships, _ships, _decks} = window
     {isCombined, isWater, battleComment, battlePackets, battlePacketsNonce, battleNonce, battleType, battleFlow} = @state
+    isStateChanged = false

     # Game states
     switch path
       when '/kcsapi/api_req_map/start', '/kcsapi/api_req_map/next'
+        isStateChanged = true
         sortie = __ "Sortie"
         mapArea = body.api_maparea_id
         mapCell = body.api_mapinfo_no
         mapSpot = body.api_no
         battleComment = "#{sortie} #{mapArea}-#{mapCell} (#{mapSpot})"
       when '/kcsapi/api_req_member/get_practice_enemyinfo'
+        isStateChanged = true
         practice = __ "Pratice"
         name = body.api_nickname
         level = body.api_level
@@ -119,7 +122,6 @@

     # Battle Packets Management
     isBattle = false
-    packet = body
     timestamp = new Date().getTime()
     switch path
       when '/kcsapi/api_req_sortie/battle', '/kcsapi/api_req_practice/battle', '/kcsapi/api_req_sortie/airbattle'
@@ -136,7 +138,7 @@
           isCombined = false
           sortieID = body.api_dock_id - 1
           combinedID = null
-          # Dont update packet metadata and fleet info
+          # Dont update packet metadata
           path = body.poi_uri
           timestamp = body.poi_timestamp
           battleComment = body.poi_comment
@@ -152,6 +154,7 @@
         combinedID = null

     if isBattle
+      isStateChanged = true
       updatePacketWithFleetInfo body, isCombined, isWater, sortieID, combinedID
       updatePacketWithMetadata body, path, timestamp, battleComment
       battlePackets.unshift body
@@ -163,15 +166,17 @@
         {battleType, battleFlow} = parseBattleFlow body
         battleNonce = updateNonce battleNonce

-    @setState
-      isCombined: isCombined
-      isWater: isWater
-      battleComment: battleComment
-      battlePackets: battlePackets
-      battlePacketsNonce: battlePacketsNonce
-      battleNonce: battleNonce
-      battleType: battleType
-      battleFlow: battleFlow
+    # update state
+    if isStateChanged
+      @setState
+        isCombined: isCombined
+        isWater: isWater
+        battleComment: battleComment
+        battlePackets: battlePackets
+        battlePacketsNonce: battlePacketsNonce
+        battleNonce: battleNonce
+        battleType: battleType
+        battleFlow: battleFlow

   # API for Component <OptionArea />
   shouldAutoShow: true


Delete transform.coffee

Delete transform.coffee

--- transform.coffee
+++ transform.coffee
@@ -1,62 +0,0 @@
-class Transform
-
-
-#             {
-#               "lang": "R",    // function language
-#               "function": "fibonnaci", // function name
-#                "properties": {
-#                  "data" : "static",
-#                  "length" : 20,
-#                  "field" : "x",
-#                 "name": "fibonnaci_x"
-#                }
-#          }
-
-Transform::process = (obj) ->
-  for i in obj
-    if i.hasOwnProperty("lang") and i.lang == "R"
-      Transform.prototype["R_" + i.function](i.properties)
-    else
-      Transform.prototype[i.function](i.properties)
-
-
-
-
-        #j {log_x: Math.log(j.x)    ,x:5}
-
-
-
-
-Transform::pow = (obj)->
-  dataTable = lib.GoG_JSON[obj.data]
-  power = obj.power
-  field = obj.field
-  variable = obj.name
-
-  for j in dataTable
-    for key, value of j
-      j[variable] = Math.pow(j[field], power)
-
-
-
-Transform::R_fibonnaci = (obj) ->
-  dataTable = lib.GoG_JSON[obj.data]
-  variable = obj.name
-  field = obj.field
-  length = obj.length
-  library = obj.library
-  data = {n : length, sequence: true}
-
-  ocpu.seturl "http://localhost:5888/ocpu/library/"+library+"/R"
-
-  ocpu.rpc "fibonacci", data , (output) ->
-    m = 0
-    for j in dataTable
-      j[variable] = output[m]
-      m++
-
-  return
-
-
-
-


:lipstick:

:lipstick:

--- tasks/download-node-task.coffee
+++ tasks/download-node-task.coffee
@@ -32,17 +32,13 @@
     done = @async()

     {version} = grunt.config(@name)
-    downloadURL =
-      if process.platform is 'win32'
-        arch = if process.arch is 'x64' then 'x64/' else ''
-        "http://nodejs.org/dist/#{version}/#{arch}node.exe"
-      else
-        "http://nodejs.org/dist/#{version}/node-#{version}-#{process.platform}-#{process.arch}.tar.gz"
-    filename =
-      if process.platform is 'win32'
-        path.join('bin', "node_win32_#{process.arch}.exe")
-      else
-        path.join('bin', "node_#{process.platform}_#{process.arch}")
+    if process.platform is 'win32'
+      arch = if process.arch is 'x64' then 'x64/' else ''
+      downloadURL = "http://nodejs.org/dist/#{version}/#{arch}node.exe"
+      filename = path.join('bin', "node_win32_#{process.arch}.exe")
+    else
+      downloadURL = "http://nodejs.org/dist/#{version}/node-#{version}-#{process.platform}-#{process.arch}.tar.gz"
+      filename = path.join('bin', "node_#{process.platform}_#{process.arch}")

     if fs.existsSync(filename)
       done()


passing presentation functionality into data callbacks in homepage.coffee; better documentation;

--- app/assets/javascripts/homepage.coffee
+++ app/assets/javascripts/homepage.coffee
@@ -5,54 +5,85 @@
 #  or by the full text state name (e.g., 'NY' or 'New York')
 # @param String selector
 #  The containing element in which a single state's gas info will be drawn.
-# @param String state
-#  The full text or postal-abbreviated state name.
-getStateNameAndGasPrice = (selector, state) ->
+# @param String stateName
+#  Full text or postal-abbreviated state name.
+# @param Function drawCallback
+#  Callback function for printing the API response data to the page.
+# @param Function errorCallback
+#  Callback function for printing an error to the page.
+# @return VOID
+getStateNameAndGasPrice = (selector, stateName, drawCallback, errorCallback) ->
   $.ajax
-    url: '/api/v1/states/' + state
+    url: '/api/v1/states/' + stateName
     dataType: 'json'
     error: (jqXHR, textStatus, errorThrown) ->
-      handleGasInfoErrors selector, 'Error: invalid US state.'
+      errorCallback selector, 'Error: invalid US state.'
     success: (data, textStatus, jqXHR) ->
       if data.state
-        $('#state-gas-price').hide()
-        state = data.state
-        list  = $('<ul>').addClass('state-list list-group')
-        name  = $('<span>').addClass('state-name').text(state.name)
-        price = $('<span>').addClass('state-price badge').text(state.price)
-        list.append($('<li>').addClass('list-group-item').append(name).append(price))
-        $('#state-gas-price').html(list)
-        $('#state-gas-price').fadeIn 'fast', ->
-          $(this).effect 'shake', {direction: 'down', distance: 10, times: 2}
+        drawCallback selector, data.state
       else
-        handleGasInfoErrors selector, 'Error: invalid US state.'
+        errorCallback selector, 'Error: invalid US state.'

 # Hits API for list of States and their gas prices. If prices are out of date,
 #  or there are fewer than 50 States, the list is refreshed. This is called by
 #  the document.ready routine, defined below.
 # @param String selector
-#   The containing element in which gas price information is drawn.
-getStateNamesAndGasPrices = (selector) ->
+#  The containing element in which a single state's gas info will be drawn.
+# @param Function drawCallback
+#  Callback function for printing the API response data to the page.
+# @param Function errorCallback
+#  Callback function for printing an error to the page.
+# @return VOID
+getAllStateNamesAndGasPrices = (selector, drawCallback, errorCallback) ->
   $.ajax
     url: '/api/v1/states'
     dataType: 'json'
     error: (jqXHR, textStatus, errorThrown) ->
-      handleGasInfoErrors selector, 'There was an issue processing this request. Please try again.'
+      errorCallback selector, 'There was an issue processing this request. Please try again.'
     success: (data, textStatus, jqXHR) ->
       if data.states
-        states = data.states
-        list   = $('<ul>').addClass 'all-states-list list-group'
-        for state in states
-          name  = $('<span>').addClass('state-name').text(state.name)
-          price = $('<span>').addClass('state-price badge').text(state.price)
-          list.append $('<li>').addClass('list-group-item').append(name).append(price)
-        $('#all-gas-prices').hide()
-        $('#all-gas-prices').html list
-        $('#all-gas-prices').fadeIn 'slow'
+        drawCallback selector, data.states
       else
-        handleGasInfoErrors selector, 'Error: no states found'
+        errorCallback selector, 'Error: no states found'
+
+# Draws / prints a state name and gas price to the selector.
+# @param String selector
+#  The containing element in which a single state's gas info will be drawn.
+# @param Obj states
+#  Object containing state name and gas price.
+# @return VOID
+drawStateData = (selector, state) ->
+  $(selector).hide()
+  list  = $('<ul>').addClass('state-list list-group')
+  name  = $('<span>').addClass('state-name').text(state.name)
+  price = $('<span>').addClass('state-price badge').text(state.price)
+  list.append($('<li>').addClass('list-group-item').append(name).append(price))
+  $(selector).html(list)
+  $(selector).fadeIn 'fast', ->
+    $(this).effect 'shake', {direction: 'down', distance: 10, times: 2}
+
+# Draws / prints all state names and gas prices to the selector.
+# @param String selector
+#  The containing element in which a single state's gas info will be drawn.
+# @param Obj states
+#  Object containing list of state names and gas price objects.
+# @return VOID
+drawAllStateData = (selector, states) ->
+  list = $('<ul>').addClass 'all-states-list list-group'
+  for state in states
+    name  = $('<span>').addClass('state-name').text(state.name)
+    price = $('<span>').addClass('state-price badge').text(state.price)
+    list.append $('<li>').addClass('list-group-item').append(name).append(price)
+  $(selector).hide()
+  $(selector).html list
+  $(selector).fadeIn 'slow'

 # Replaces the given selector's content with an error message
+# @param String selector
+#  The containing element in which an error will be printed.
+# @param String message
+#  The error to be printed.
+# @return VOID
 handleGasInfoErrors = (selector, message) ->
   $(selector).html message

@@ -61,13 +92,12 @@
 $(document).on 'ready page:load', ->
   # Listen for button click
   $('#state-btn').on 'click', ->
-    getStateNameAndGasPrice '#state-gas-price', $('#state-input').val()
+    getStateNameAndGasPrice '#state-gas-price', $('#state-input').val(), drawStateData, handleGasInfoErrors

-  # Detect 'Enter' key, since there is no real webform
+  # Detect 'Enter' key on input field
   $('#state-input').keypress (event) ->
     if event.keyCode == 13
-      getStateNameAndGasPrice '#state-gas-price', $(this).val()
+      getStateNameAndGasPrice '#state-gas-price', $(this).val(), drawStateData, handleGasInfoErrors

   # Load initial data onto homepage from server
-  getStateNamesAndGasPrices '#all-gas-prices'
-  return
+  getAllStateNamesAndGasPrices '#all-gas-prices', drawAllStateData, handleGasInfoErrors


nothingness tests for simple driver

nothingness tests for simple driver

--- test/driver/simpleDriver.coffee
+++ test/driver/simpleDriver.coffee
@@ -202,6 +202,50 @@
       })
       done()

+  it "does handles nothingness", (done) ->
+    querySpec = [
+      { operation: 'filter', type: 'false' }
+    ]
+    diamondsDriver { query: new FacetQuery(querySpec) }, (err, result) ->
+      expect(err).to.equal(null)
+      expect(result).to.deep.equal({
+        "prop": {}
+      })
+      done()
+
+  it "does handles nothingness with apply", (done) ->
+    querySpec = [
+      { operation: 'filter', type: 'false' }
+      { operation: 'apply', name: 'Count', aggregate: 'count' }
+    ]
+    diamondsDriver { query: new FacetQuery(querySpec) }, (err, result) ->
+      expect(err).to.equal(null)
+      expect(result).to.deep.equal({
+        "prop": {
+          "Count": 0
+        }
+      })
+      done()
+
+  it "does handles nothingness with split", (done) ->
+    querySpec = [
+      { operation: 'filter', type: 'false' }
+      { operation: 'apply', name: 'Count', aggregate: 'count' }
+
+      { operation: 'split', name: 'Cut', bucket: 'identity', attribute: 'cut' }
+      { operation: 'apply', name: 'Count', aggregate: 'count' }
+      { operation: 'combine', method: 'slice', sort: { prop: 'Count', compare: 'natural', direction: 'descending' }, limit: 2 }
+    ]
+    diamondsDriver { query: new FacetQuery(querySpec) }, (err, result) ->
+      expect(err).to.equal(null)
+      expect(result).to.deep.equal({
+        "prop": {
+          "Count": 0
+        }
+        "splits": []
+      })
+      done()
+
   it "does a maxTime query", (done) ->
     querySpec = [
       { operation: 'apply', name: 'Max', aggregate: 'max', attribute: 'time' }


updated timeout to 8s

updated timeout to 8s

--- grunt/exec.coffee
+++ grunt/exec.coffee
@@ -1,9 +1,9 @@
 module.exports = (grunt) ->
   grunt.config 'exec',
     crawl:
-      cmd: 'phantomjs crawler.coffee http://localhost:<%= express.all.options.port %>/ build/ 3000 "docs|test"'
+      cmd: 'phantomjs crawler.coffee http://localhost:<%= express.all.options.port %>/ build/ 8000 "docs|test"'
     e2e:
       cmd: 'protractor test/e2e/protractor.js'
       stdout: !process.env.TRAVIS

-  grunt.loadNpmTasks 'grunt-exec'+  grunt.loadNpmTasks 'grunt-exec'


Exclude layout.jade

Exclude layout.jade


fixing fetcher test

fixing fetcher test

--- test/shared/fetcher.test.coffee
+++ test/shared/fetcher.test.coffee
@@ -1,7 +1,16 @@
+require('../../shared/globals')
 fetcher = require('../../shared/fetcher')
 should = require('should')
-Listing = require('../../app/models/listing')
-Listings = require('../../app/collections/listings')
+
+modelUtils = require('../../shared/model_utils')
+BaseModel = require('../../shared/base/model')
+BaseCollection = require('../../shared/base/collection')
+
+class Listing extends BaseModel
+class Listings extends BaseCollection
+
+modelUtils.addClassMapping 'Listing', Listing
+modelUtils.addClassMapping 'Listings', Listings

 describe 'fetcher', ->


fix typo

fix typo

--- tests/karma/browserstack.coffee
+++ tests/karma/browserstack.coffee
@@ -14,7 +14,7 @@
   'windows-8-firefox' : ['Windows', '8', 'firefox', '24.0']
   'windows-8-safari'  : ['Windows', '8', 'safari', '5.1']
   'windows-8-ie-10'   : ['Windows', '8', 'ie', '10.0']
-
+
   'windows-7-ie-9'    : ['Windows', '7', 'ie', '9.0']
   'windows-7-ie-8'    : ['Windows', '7', 'ie', '8.0']

@@ -40,7 +40,7 @@
 options.basePath = 'build'
 options.customLaunchers = customLaunchers
 options.exclude = ['tests/mocha/editor.js']
-options.reporters = ['dot']
+options.reporters = ['dots']

 browserGroups = _.groupBy(browserList, (browser, i) ->
   return Math.floor(i / BROWSERSTACK_PARALLEL)


Cleanup

Cleanup

--- layout.coffee
+++ layout.coffee
@@ -910,15 +910,14 @@
   keyboard = new Keyboard()

-  exports = {
-    view: View,
-    class: Class,
-    node: Node,
-    layout: Layout,
-    simplelayout: SimpleLayout,
-    initViews: init,
+  exports =
+    view: View
+    class: Class
+    node: Node
+    layout: Layout
+    simplelayout: SimpleLayout
+    initViews: init
     writeDefaultStyle: writeDefaultStyle
-  }

 lz.writeDefaultStyle()


Move to setAttribute with a skip arg

Move to setAttribute with a skip arg

--- layout.coffee
+++ layout.coffee
@@ -10,7 +10,7 @@
     # if (view[name] != value and view?.events?[name])
       # console.log('sending style', name, elem.$view._locked) if sendstyle
       # view.setAttribute(name, value, true)
-      view.gotStyle(name, value)
+      view.setAttribute(name, value, true)

     returnval

@@ -373,13 +373,8 @@
       super(el, attributes)
       # console.log 'new view', el, attributes, @

-    gotStyle: (name, value) ->
-      if not ignoredAttributes[name]
-        # if view.events?[name])
-        _super::setAttribute.apply(@, arguments)
-
-    setAttribute: (name, value) ->
-      if not (ignoredAttributes[name] or @[name] == value)
+    setAttribute: (name, value, skip) ->
+      if not (skip or ignoredAttributes[name] or @[name] == value)
         # console.log 'setting style', name, @[name], value, @
         @sprite.setStyle(name, value)
       super(name, value)


one more example

one more example


after all I like this ( reverted original )

--- lib/ui.coffee
+++ lib/ui.coffee
@@ -739,15 +739,13 @@

   moveToSearchedWordAtSelectedItem: ->
     if @items.hasSelectedItem()
-      point = @items.getFirstPositionForSelectedItem()
-
       if @isInSyncToProviderEditor()
-        point.column += @provider.editor.getCursorBufferPosition().column
+        column = @provider.editor.getCursorBufferPosition().column
       else
         text = @items.getSelectedItem().text
-        match = cloneRegExp(@provider.initiallySearchedRegexp).exec(text)
-        point.column += match.index
-
+        column = cloneRegExp(@provider.initiallySearchedRegexp).exec(text).index
+
+      point = @items.getFirstPositionForSelectedItem().translate([0, column])
       @editor.setCursorBufferPosition(point)

   moveToPrompt: ->


Update `command_back` and `command_forward`

--- extension/packages/commands.coffee
+++ extension/packages/commands.coffee
@@ -160,11 +160,11 @@

 # Go back in history
 command_back = (vim) ->
-  vim.window.history.back()
+  vim.rootWindow.BrowserBack()

 # Go forward in history
 command_forward = (vim) ->
-  vim.window.history.forward()
+  vim.rootWindow.BrowserForward()

 # Close current tab
 command_close_tab = (vim) ->


Updates the ini snippet

Updates the ini snippet

--- snippets/ini.cson
+++ snippets/ini.cson
@@ -1,4 +1,4 @@
 '.source.inspec':
   'Describe ini':
     'prefix': 'ini'
-    'body': "# http://inspec.io/docs/reference/resources/ini/\ndescribe ini('${1:name}') do\n  it { should${2:_not} ${3:exist} }${4}\nend"
+    'body': "# http://inspec.io/docs/reference/resources/ini/\ndescribe ini('${1:path}') do\n  its('${2:setting_name}') { should${3:_not} eq '${4:value}' }${5}\nend"


Misread description of Smack Down; unnecessary test.

--- test/bw/moves.coffee
+++ test/bw/moves.coffee
@@ -4782,5 +4782,3 @@
       mock = @sandbox.mock(telekinesis).expects('fail').once()
       @battle.performMove(@id1, telekinesis)
       mock.verify()
-
-    it "nullifies Arena Trap"


Fixed typo in url method

Fixed typo in url method

--- source/zen.coffee
+++ source/zen.coffee
@@ -31,7 +31,7 @@

   _url = ->
     url = "#{ZEN.instance.host}"
-    url += ":#{ZEN.intance.port}" if ZEN.instance.port
+    url += ":#{ZEN.instance.port}" if ZEN.instance.port
     url += "/monitor/#{ZEN.instance.password}"

   _utc = (object) ->


cooldown finilazation

cooldown finilazation

--- test/cooldown.coffee
+++ test/cooldown.coffee
@@ -108,7 +108,7 @@
   obj.cooldown 'health',
     target: 10

-  5.ti
-  obj.update()
+  5.times ->
+    obj.update()

 module()


download: test file with cache and md5 stirng

--- test/download.coffee
+++ test/download.coffee
@@ -339,3 +339,28 @@
           return next err if err
           exists.should.be.true
           next()
+
+    they 'cache dir with md5 string', (ssh, next) ->
+      # Download a non existing file
+      source = 'http://localhost:12345'
+      destination = "#{scratch}/download"
+      mecano
+        ssh: ssh
+      .write
+        destination: "#{scratch}/a_file"
+        content: 'okay'
+      .download
+        source: "#{scratch}/a_file"
+        destination: "#{scratch}/download_test"
+        cache_dir: "#{scratch}/cache_dir"
+        md5: 'df8fede7ff71608e24a5576326e41c75'
+      , (err, downloaded) ->
+        return next err if err
+        downloaded.should.be.true
+        fs.readFile ssh, "#{scratch}/cache_dir/a_file", 'ascii', (err, data) ->
+          return next err if err
+          data.should.eql 'okay'
+          fs.readFile ssh, "#{scratch}/download_test", 'ascii', (err, data) ->
+            return next err if err
+            data.should.eql 'okay'
+            next()


Improve convo shuffling and give up on guess who

--- scripts/nostalgia.coffee
+++ scripts/nostalgia.coffee
@@ -10,7 +10,8 @@
 #   nostalgiabot Start Guess Who - Start a game of Guess Who!
 #   nostalgiabot Show Guess Who - Show the current quote to guess
 #   nostalgiabot Guess <person> - Guess who said the current quote. Ends when guessed correctly.
-#   nostalgiabot End Guess Who - End the game of Guess Who!
+#   nostalgiabot End Guess Who - End the game of Guess Who!.
+#   nostalgiabot Give up - End the game of Guess Who! and get the answer.
 #   nostalgiabot Hacker me - Get a 100% real quote from a professional hacker.
 #   nostalgiabot BS me - Get a technobable quote that sounds almost real.
 #   nostalgiabot Commit message me - Generate your next commit message
@@ -65,31 +66,53 @@
     else
         res.send "I don't remember #{displayName}"

+shuffleNames = (names) ->
+    i = names.length
+    while --i
+        j = Math.floor(Math.random() * (i+1))
+        [names[i], names[j]] = [names[j], names[i]] # use pattern matching to swap
+
+    return names
+
 convoRespond = (res) ->
     allNames = (res.match[1].toLowerCase().trim() + " " + res.match[2].toLowerCase().trim()).split(",")
-
-    # Generate quotes
-    convoLines = []
+    fixedNames = []
     for name in allNames
         name = name.toLowerCase().trim()
+        fixedNames.push name
+    allNames = fixedNames
+
+    # Generate quotes
+    convoMap = {}
+    for name in allNames
         if !(name of memories)
             res.send "I don't recognize #{name}"
             return

-        convoLines.push "#{name}: " + (res.random memories[name])
-        convoLines.push "#{name}: " + (res.random memories[name])
-
-
-    # Shuffle quotes
-    i = convoLines.length
-    while --i
-        j = Math.floor(Math.random() * (i+1))
-        [convoLines[i], convoLines[j]] = [convoLines[j], convoLines[i]] # use pattern matching to swap
+        firstQuote = (res.random memories[name])
+        secondQuote = (res.random memories[name])
+        while secondQuote == firstQuote
+            secondQuote = (res.random memories[name])
+
+        personQuotes = []
+        personQuotes.push "#{name}: " + firstQuote
+        personQuotes.push "#{name}: " + secondQuote
+        convoMap[name] = personQuotes
+
+    allNames = Object.keys(convoMap)

     # Assemble quotes
     convo = ""
-    for line in convoLines
-        convo += line + "\n"
+    lastName = ""
+    i = 2
+    while i--
+        allNames = shuffleNames(allNames)
+        while allNames[0] == lastName && allNames.length > 1
+            allNames = shuffleNames(allNames)
+        lastName = allNames[allNames.length-1]
+
+        for name in allNames
+            convo += convoMap[name][i] + "\n"

     res.send convo

@@ -210,6 +233,10 @@
     guessWhoQuote = ''
     res.send "Guess Who game over"

+giveUpRespond = (res) ->
+    res.send "You gave up! #{toTitleCase guessWhoTarget} said \"#{guessWhoQuote}\""
+    endGuessWhoRespond(res)
+

 bobRossOnVacation = false
 returnFromVacation = () ->
@@ -254,6 +281,7 @@
     robot.respond /show guess who/i, showGuessWhoQuoteRespond
     robot.respond /guess (.*)/i, guessRespond
     robot.respond /end guess who/i, endGuessWhoRespond
+    robot.respond /give up/i, giveUpRespond

     robot.hear /.*a bug.*/i, bobRossRespond


Lint correction

Lint correction

--- server/collection.coffee
+++ server/collection.coffee
@@ -280,4 +280,3 @@
       _id: @personId
     ,
       fields: _.extend Collection.readAccessPersonFields()
-


use socket.end for tcp checks

use socket.end for tcp checks

--- services/clsi/app.coffee
+++ services/clsi/app.coffee
@@ -131,17 +131,19 @@
 server = net.createServer (socket) ->
 	socket.on "error", (err)->
 		logger.err err:err, "error with socket on load check"
+		socket.destroy()
+
 	currentLoad = os.loadavg()[0]
 	availableWorkingCpus = os.cpus().length - 1
 	freeLoad = availableWorkingCpus - currentLoad
 	freeLoadPercentage = Math.round((freeLoad / availableWorkingCpus) * 100)
-	if freeLoadPercentage < 0
+	if freeLoadPercentage <= 0
 		freeLoadPercentage = 1 # when its 0 the server is set to drain and will move projects to different servers
-	socket.write "up, #{freeLoadPercentage}%\n", "ASCII"
-	socket.destroy()
+	socket.write("up, #{freeLoadPercentage}%\n", "ASCII")
+	socket.end()

 server.listen port = (Settings.internal?.clsi?.load_port or 3044),  ->
-  console.log "listening on port #{port}"
-  # netcat 127.0.0.1 3044
+  logger.info "tcp load endpoint listening on port #{port}"
+  # telnet 127.0.0.1 3044


Fixing video regression

Fixing video regression

--- src/assets.coffee
+++ src/assets.coffee
@@ -34,6 +34,7 @@
 		posterSrc: -> @imgSrc 'poster'
 		imageSrc: -> @imgSrc 'image'
 		fallbackSrc: -> @imgSrc 'fallback'
+		videoSrc: -> @video # Passthrough, so all assets have a src

 		# Return whether a fallback image should be shown
 		useFallback: -> switch


Add reportNotificationClick

Add reportNotificationClick

--- src/Carrot.coffee
+++ src/Carrot.coffee
@@ -166,6 +166,9 @@
           callback(carrotResponse) if callback
       )

+  reportNotificationClick: (notifId, callback) ->
+    @ajaxPost("#{@scheme}://parsnip.gocarrot.com/notification_click", {user_id: @udid, platform_id: notifId})
+
   reportFeedClick: (postId, callback) ->
     @ajaxPost("#{@scheme}://posts.gocarrot.com/#{postId}/clicks", {clicking_user_id: @udid, sig: "s"}, callback)


api.vm: Set vcpus max.

api.vm: Set vcpus max.

--- src/api/vm.coffee
+++ src/api/vm.coffee
@@ -455,6 +455,9 @@
         yield xapi.call 'VM.set_VCPUs_max', ref, "#{CPUs}"
       yield xapi.call 'VM.set_VCPUs_at_startup', ref, "#{CPUs}"

+  if 'cpusMax' of params
+    yield xapi.call 'VM.set_VCPUs_max', ref, "#{CPUs}"
+
   # HA policy
   # TODO: also handle "best-effort" case
   if 'high_availability' of params
@@ -508,6 +511,8 @@

   # Number of virtual CPUs to allocate.
   CPUs: { type: 'integer', optional: true }
+
+  cpusMax: { type: ['integer', 'string'], optional: true }

   # Memory to allocate (in bytes).
   #


Queue store operations and process them in parallel.

--- src/broker.coffee
+++ src/broker.coffee
@@ -8,6 +8,10 @@
     @store  = new Riak @options.store.options
     @router = zmq.socket "router"
     @dealer = zmq.socket "dealer"
+    @queue = async.queue (task, callback) =>
+      @store.write task.id, task, callback
+    , 8
+
     @_bindRouter()
     @_bindDealer()
     @_submitTasks()
@@ -27,7 +31,7 @@
   _routerMessage: (envelopes..., payload) =>
     task = JSON.parse payload

-    @store.write task.id, task, (error) =>
+    @queue.push task, (error) =>
       if not error?
         @dealer.send [envelopes, payload]

@@ -41,7 +45,6 @@

   _dealerMessage: (envelopes..., payload) =>
     task = JSON.parse payload
-
     @store.delete task.id, (error) =>
       @router.send [envelopes, payload]


use npm's built in node-gyp

use npm's built in node-gyp

--- spec/install-spec.coffee
+++ spec/install-spec.coffee
@@ -538,7 +538,8 @@
       beforeEach ->
         # Normally npm_config_node_gyp would be ignored, but it works here because we're calling apm
         # directly and not through the scripts in bin/
-        fs.copySync path.join(nodeModules, 'node-gyp'), path.join(nodeModules, 'with a space')
+        nodeGypPath = path.join(nodeModules, 'npm', 'node_modules', 'node-gyp')
+        fs.copySync nodeGypPath, path.join(nodeModules, 'with a space')
         process.env.npm_config_node_gyp = path.join(nodeModules, 'with a space', 'bin', 'node-gyp.js')

         # Read + execute permission


Fix Project spec

Fix Project spec

--- spec/project-spec.coffee
+++ spec/project-spec.coffee
@@ -62,7 +62,7 @@
       expect(project.getEditSessions()[0]).toBe editSession1
       expect(project.getEditSessions()[1]).toBe editSession2

-  describe ".open(path)", ->
+  describe ".openSync(path)", ->
     [fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = []
     beforeEach ->
       absolutePath = require.resolve('./fixtures/dir/a')
@@ -117,7 +117,7 @@
         expect(project.openSync(pathToOpen, hey: "there")).toEqual { foo: pathToOpen, options: {hey: "there"} }
         expect(project.openSync("bar://baz")).toEqual { bar: "bar://baz" }

-  describe ".openAsync(path)", ->
+  describe ".open(path)", ->
     [fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = []

     beforeEach ->
@@ -141,7 +141,7 @@
         it "returns a new edit session for the given path and emits 'buffer-created' and 'edit-session-created' events", ->
           editSession = null
           waitsForPromise ->
-            project.openAsync(absolutePath).then (o) -> editSession = o
+            project.open(absolutePath).then (o) -> editSession = o

           runs ->
             expect(editSession.buffer.getPath()).toBe absolutePath
@@ -152,7 +152,7 @@
         it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'edit-session-created' events", ->
           editSession = null
           waitsForPromise ->
-            project.openAsync(absolutePath).then (o) -> editSession = o
+            project.open(absolutePath).then (o) -> editSession = o

           runs ->
             expect(editSession.buffer.getPath()).toBe absolutePath
@@ -163,7 +163,7 @@
         it "returns a new edit session containing currently opened buffer and emits a 'edit-session-created' event", ->
           editSession = null
           waitsForPromise ->
-            project.openAsync(absolutePath).then (o) -> editSession = o
+            project.open(absolutePath).then (o) -> editSession = o

           runs ->
             newBufferHandler.reset()
@@ -176,7 +176,7 @@
         it "returns a new edit session and emits 'buffer-created' and 'edit-session-created' events", ->
           editSession = null
           waitsForPromise ->
-            project.openAsync().then (o) -> editSession = o
+            project.open().then (o) -> editSession = o

           runs ->
             expect(editSession.buffer.getPath()).toBeUndefined()
@@ -187,17 +187,17 @@
       it "returns the resource returned by the custom opener", ->
         waitsForPromise ->
           pathToOpen = project.resolve('a.foo')
-          project.openAsync(pathToOpen, hey: "there").then (item) ->
+          project.open(pathToOpen, hey: "there").then (item) ->
             expect(item).toEqual { foo: pathToOpen, options: {hey: "there"} }

         waitsForPromise ->
-          project.openAsync("bar://baz").then (item) ->
+          project.open("bar://baz").then (item) ->
             expect(item).toEqual { bar: "bar://baz" }

     it "returns number of read bytes as progress indicator", ->
       filePath = project.resolve 'a'
       totalBytes = 0
-      promise = project.openAsync(filePath)
+      promise = project.open(filePath)
       promise.progress (bytesRead) -> totalBytes = bytesRead

       waitsForPromise ->
@@ -220,11 +220,11 @@
         buffer = project.bufferForPathSync("a").retain().release()
         expect(project.bufferForPathSync("a").retain().release()).not.toBe buffer

-  describe ".bufferForPathAsync(path)", ->
+  describe ".bufferForPath(path)", ->
     [buffer] = []
     beforeEach ->
       waitsForPromise ->
-        project.bufferForPathAsync("a").then (o) ->
+        project.bufferForPath("a").then (o) ->
           buffer = o
           buffer.retain()

@@ -234,18 +234,18 @@
     describe "when opening a previously opened path", ->
       it "does not create a new buffer", ->
         waitsForPromise ->
-          project.bufferForPathAsync("a").then (anotherBuffer) ->
+          project.bufferForPath("a").then (anotherBuffer) ->
             expect(anotherBuffer).toBe buffer

         waitsForPromise ->
-          project.bufferForPathAsync("b").then (anotherBuffer) ->
+          project.bufferForPath("b").then (anotherBuffer) ->
             expect(anotherBuffer).not.toBe buffer

       it "creates a new buffer if the previous buffer was destroyed", ->
         buffer.release()

         waitsForPromise ->
-          project.bufferForPathAsync("b").then (anotherBuffer) ->
+          project.bufferForPath("b").then (anotherBuffer) ->
             expect(anotherBuffer).not.toBe buffer

   describe ".resolve(uri)", ->


keep node 0.10 require happy

keep node 0.10 require happy

--- specs/test-helper.coffee
+++ specs/test-helper.coffee
@@ -8,7 +8,7 @@

 testConfig = require('./config.json')
 sourceFolder = path.resolve(__dirname, '../src')
-requireSrc = (pathToFile) -> require(path.resolve(sourceFolder, pathToFile))
+requireSrc = (pathToFile = ".") -> require(path.resolve(sourceFolder, pathToFile))

 sql = requireSrc('sql')
 SqlFormatter = requireSrc('dialects/sql-formatter')


flux/teams: add getter to hold admins

flux/teams: add getter to hold admins

--- client/app/lib/flux/teams/getters.coffee
+++ client/app/lib/flux/teams/getters.coffee
@@ -80,6 +80,7 @@
     members.filter (member) -> isValidMemberValue member, value
 ]

+
 filteredMembersWithRoleAndDisabledUsers = [
   filteredMembersWithRole
   disabledUsers
@@ -87,6 +88,14 @@
     users.withMutations (users) ->
       disabledUsers.map (disabledUser) ->
         users.set disabledUser.get('_id'), disabledUser
+]
+
+
+adminsList = [
+  filteredMembersWithRole
+  (users) ->
+    users.filter (user) ->
+      user.get('status') isnt 'pending' and user.get('role') is 'admin'  if user
 ]

@@ -147,4 +156,5 @@
   resendInvitations
   disabledUsers
   filteredMembersWithRoleAndDisabledUsers
+  adminsList
 }


Added hook `rpcCall`

Added hook `rpcCall`

--- client/modules/packages/rpc/index.coffee
+++ client/modules/packages/rpc/index.coffee
@@ -18,8 +18,8 @@

 # ## Implements hook `service`
 exports.$service = -> [
-	'$injector', '$q', 'require', 'socket'
-	({invoke}, {defer}, require, {emit}) ->
+	'$injector', '$q', 'require', 'pkgman', 'socket'
+	({invoke}, {defer}, require, pkgman, {emit}) ->

 		service = {}

@@ -50,22 +50,22 @@
 			deferred = defer()

 			emit "rpc://#{route}", data, ({error, result}) ->
+				if error?
+					deferred.reject errors.unserialize error
+				else
+					deferred.resolve result
+
+			invoke(
+				injectable, null

-				if error?
-
-					error = errors.unserialize error
-
-					# `TODO`: This should be middleware'd.
-					notifications.add(
-						class: 'alert-danger'
-						text: errors.message error
-					) if notifications?
-
-					deferred.reject error
-
-				else
-
-					deferred.resolve result
+				route: route
+				data: data
+				result: deferred.promise
+
+			) for injectable in pkgman.invokeFlat(
+				'rpcCall', route, data, deferred.promise
+
+			)

 			deferred.promise


Emit complete/error events from the handle.

--- src/client.coffee
+++ src/client.coffee
@@ -50,6 +50,7 @@
   _completed: (handle, data) ->
     console.log "Task completed: %s", handle.id
     @_removeHandle handle
+    handle.emit "complete", data

   _failed: (handle, data) ->
     console.log "Task failed: %s", handle.id
@@ -57,6 +58,7 @@
       handle.callback data
       handle.callback = undefined
     @_removeHandle handle
+    handle.emit "error", data

   _addHandle: (handle) ->
     @handles[handle.id] = handle


Actually track bounties

Actually track bounties

The bounty deposit and withdraw calls weren't being tracked as reward transacations.

--- src/coffee.coffee
+++ src/coffee.coffee
@@ -259,8 +259,8 @@
           coffeeconomy.deposit client, dibsLimit - 1

           if hasBounty()
-            coffeeconomy.withdraw bounty.issuer, bounty.reward
-            coffeeconomy.deposit client, bounty.reward
+            coffeeconomy.withdraw bounty.issuer, bounty.reward, true
+            coffeeconomy.deposit client, bounty.reward, true
         else
           coffeeconomy.withdraw client, 1


Conditionally include deprecations in Config

--- src/config.coffee
+++ src/config.coffee
@@ -371,13 +371,13 @@
   observe: ->
     if arguments.length is 2
       [keyPath, callback] = arguments
-    else if arguments.length is 3 and (_.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor)
+    else if Grim.includeDeprecations and arguments.length is 3 and (_.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor)
       Grim.deprecate """
         Passing a scope descriptor as the first argument to Config::observe is deprecated.
         Pass a `scope` in an options hash as the third argument instead.
       """
       [scopeDescriptor, keyPath, callback] = arguments
-    else if arguments.length is 3 and (_.isString(arguments[0]) and _.isObject(arguments[1]))
+    else if Grim.includeDeprecations and arguments.length is 3 and (_.isString(arguments[0]) and _.isObject(arguments[1]))
       [keyPath, options, callback] = arguments
       scopeDescriptor = options.scope
       if options.callNow?
@@ -419,7 +419,7 @@
       [callback] = arguments
     else if arguments.length is 2
       [keyPath, callback] = arguments
-    else if _.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor
+    else if Grim.includeDeprecations and _.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor
       Grim.deprecate """
         Passing a scope descriptor as the first argument to Config::onDidChange is deprecated.
         Pass a `scope` in an options hash as the third argument instead.
@@ -498,7 +498,7 @@
       if typeof arguments[0] is 'string' or not arguments[0]?
         [keyPath, options] = arguments
         {scope} = options
-      else
+      else if Grim.includeDeprecations
         Grim.deprecate """
           Passing a scope descriptor as the first argument to Config::get is deprecated.
           Pass a `scope` in an options hash as the final argument instead.
@@ -578,7 +578,7 @@
   # * `true` if the value was set.
   # * `false` if the value was not able to be coerced to the type specified in the setting's schema.
   set: ->
-    if arguments[0]?[0] is '.'
+    if Grim.includeDeprecations and arguments[0]?[0] is '.'
       Grim.deprecate """
         Passing a scope selector as the first argument to Config::set is deprecated.
         Pass a `scopeSelector` in an options hash as the final argument instead.
@@ -617,7 +617,7 @@
   #   * `scopeSelector` (optional) {String}. See {::set}
   #   * `source` (optional) {String}. See {::set}
   unset: (keyPath, options) ->
-    if typeof options is 'string'
+    if Grim.includeDeprecations and typeof options is 'string'
       Grim.deprecate """
         Passing a scope selector as the first argument to Config::unset is deprecated.
         Pass a `scopeSelector` in an options hash as the second argument instead.
@@ -652,47 +652,6 @@
   getSources: ->
     _.uniq(_.pluck(@scopedSettingsStore.propertySets, 'source')).sort()

-  # Deprecated: Restore the global setting at `keyPath` to its default value.
-  #
-  # Returns the new value.
-  restoreDefault: (scopeSelector, keyPath) ->
-    Grim.deprecate("Use ::unset instead.")
-    @unset(scopeSelector, keyPath)
-    @get(keyPath)
-
-  # Deprecated: Get the global default value of the key path. _Please note_ that in most
-  # cases calling this is not necessary! {::get} returns the default value when
-  # a custom value is not specified.
-  #
-  # * `scopeSelector` (optional) {String}. eg. '.source.ruby'
-  # * `keyPath` The {String} name of the key.
-  #
-  # Returns the default value.
-  getDefault: ->
-    Grim.deprecate("Use `::get(keyPath, {scope, excludeSources: [atom.config.getUserConfigPath()]})` instead")
-    if arguments.length is 1
-      [keyPath] = arguments
-    else
-      [scopeSelector, keyPath] = arguments
-      scope = [scopeSelector]
-    @get(keyPath, {scope, excludeSources: [@getUserConfigPath()]})
-
-  # Deprecated: Is the value at `keyPath` its default value?
-  #
-  # * `scopeSelector` (optional) {String}. eg. '.source.ruby'
-  # * `keyPath` The {String} name of the key.
-  #
-  # Returns a {Boolean}, `true` if the current value is the default, `false`
-  # otherwise.
-  isDefault: ->
-    Grim.deprecate("Use `not ::get(keyPath, {scope, sources: [atom.config.getUserConfigPath()]})?` instead")
-    if arguments.length is 1
-      [keyPath] = arguments
-    else
-      [scopeSelector, keyPath] = arguments
-      scope = [scopeSelector]
-    not @get(keyPath, {scope, sources: [@getUserConfigPath()]})?
-
   # Extended: Retrieve the schema for a specific key path. The schema will tell
   # you what type the keyPath expects, and other metadata about the config
   # option.
@@ -709,12 +668,6 @@
       schema = schema.properties?[key]
     schema

-  # Deprecated: Returns a new {Object} containing all of the global settings and
-  # defaults. Returns the scoped settings when a `scopeSelector` is specified.
-  getSettings: ->
-    Grim.deprecate "Use ::get(keyPath) instead"
-    _.deepExtend({}, @settings, @defaultSettings)
-
   # Extended: Get the {String} path to the config file being used.
   getUserConfigPath: ->
     @configFilePath
@@ -731,31 +684,6 @@
     finally
       @transactDepth--
       @emitChangeEvent()
-
-  ###
-  Section: Deprecated
-  ###
-
-  getInt: (keyPath) ->
-    Grim.deprecate '''Config::getInt is no longer necessary. Use ::get instead.
-    Make sure the config option you are accessing has specified an `integer`
-    schema. See the schema section of
-    https://atom.io/docs/api/latest/Config for more info.'''
-    parseInt(@get(keyPath))
-
-  getPositiveInt: (keyPath, defaultValue=0) ->
-    Grim.deprecate '''Config::getPositiveInt is no longer necessary. Use ::get instead.
-    Make sure the config option you are accessing has specified an `integer`
-    schema with `minimum: 1`. See the schema section of
-    https://atom.io/docs/api/latest/Config for more info.'''
-    Math.max(@getInt(keyPath), 0) or defaultValue
-
-  toggle: (keyPath) ->
-    Grim.deprecate 'Config::toggle is no longer supported. Please remove from your code.'
-    @set(keyPath, !@get(keyPath))
-
-  unobserve: (keyPath) ->
-    Grim.deprecate 'Config::unobserve no longer does anything. Call `.dispose()` on the object returned by Config::observe instead.'

   ###
   Section: Internal methods used by core
@@ -1056,16 +984,6 @@

     @emitChangeEvent()

-  addScopedSettings: (source, selector, value, options) ->
-    Grim.deprecate("Use ::set instead")
-    settingsBySelector = {}
-    settingsBySelector[selector] = value
-    disposable = @scopedSettingsStore.addProperties(source, settingsBySelector, options)
-    @emitChangeEvent()
-    new Disposable =>
-      disposable.dispose()
-      @emitChangeEvent()
-
   setRawScopedValue: (keyPath, value, source, selector, options) ->
     if keyPath?
       newValue = {}
@@ -1093,11 +1011,6 @@
         event = {oldValue, newValue}
         oldValue = newValue
         callback(event)
-
-  settingsForScopeDescriptor: (scopeDescriptor, keyPath) ->
-    Grim.deprecate("Use Config::getAll instead")
-    entries = @getAll(null, scope: scopeDescriptor)
-    value for {value} in entries when _.valueForKeyPath(value, keyPath)?

 # Base schema enforcers. These will coerce raw input into the specified type,
 # and will throw an error when the value cannot be coerced. Throwing the error
@@ -1232,3 +1145,67 @@
   else
     resultObject = object
   resultObject
+
+if Grim.includeDeprecations
+  Config::restoreDefault = (scopeSelector, keyPath) ->
+    Grim.deprecate("Use ::unset instead.")
+    @unset(scopeSelector, keyPath)
+    @get(keyPath)
+
+  Config::getDefault = ->
+    Grim.deprecate("Use `::get(keyPath, {scope, excludeSources: [atom.config.getUserConfigPath()]})` instead")
+    if arguments.length is 1
+      [keyPath] = arguments
+    else
+      [scopeSelector, keyPath] = arguments
+      scope = [scopeSelector]
+    @get(keyPath, {scope, excludeSources: [@getUserConfigPath()]})
+
+  Config::isDefault = ->
+    Grim.deprecate("Use `not ::get(keyPath, {scope, sources: [atom.config.getUserConfigPath()]})?` instead")
+    if arguments.length is 1
+      [keyPath] = arguments
+    else
+      [scopeSelector, keyPath] = arguments
+      scope = [scopeSelector]
+    not @get(keyPath, {scope, sources: [@getUserConfigPath()]})?
+
+  Config::getSettings = ->
+    Grim.deprecate "Use ::get(keyPath) instead"
+    _.deepExtend({}, @settings, @defaultSettings)
+
+  Config::getInt = (keyPath) ->
+    Grim.deprecate '''Config::getInt is no longer necessary. Use ::get instead.
+    Make sure the config option you are accessing has specified an `integer`
+    schema. See the schema section of
+    https://atom.io/docs/api/latest/Config for more info.'''
+    parseInt(@get(keyPath))
+
+  Config::getPositiveInt = (keyPath, defaultValue=0) ->
+    Grim.deprecate '''Config::getPositiveInt is no longer necessary. Use ::get instead.
+    Make sure the config option you are accessing has specified an `integer`
+    schema with `minimum: 1`. See the schema section of
+    https://atom.io/docs/api/latest/Config for more info.'''
+    Math.max(@getInt(keyPath), 0) or defaultValue
+
+  Config::toggle = (keyPath) ->
+    Grim.deprecate 'Config::toggle is no longer supported. Please remove from your code.'
+    @set(keyPath, !@get(keyPath))
+
+  Config::unobserve = (keyPath) ->
+    Grim.deprecate 'Config::unobserve no longer does anything. Call `.dispose()` on the object returned by Config::observe instead.'
+
+  Config::addScopedSettings = (source, selector, value, options) ->
+    Grim.deprecate("Use ::set instead")
+    settingsBySelector = {}
+    settingsBySelector[selector] = value
+    disposable = @scopedSettingsStore.addProperties(source, settingsBySelector, options)
+    @emitChangeEvent()
+    new Disposable =>
+      disposable.dispose()
+      @emitChangeEvent()
+
+  Config::settingsForScopeDescriptor = (scopeDescriptor, keyPath) ->
+    Grim.deprecate("Use Config::getAll instead")
+    entries = @getAll(null, scope: scopeDescriptor)
+    value for {value} in entries when _.valueForKeyPath(value, keyPath)?


Convert visibility on the grammars section

--- src/editor.coffee
+++ src/editor.coffee
@@ -1357,11 +1357,11 @@
   Section: Grammars
   ###

-  # Public: Get the current {Grammar} of this editor.
+  # Essential: Get the current {Grammar} of this editor.
   getGrammar: ->
     @displayBuffer.getGrammar()

-  # Public: Set the current {Grammar} of this editor.
+  # Essential: Set the current {Grammar} of this editor.
   #
   # Assigning a grammar will cause the editor to re-tokenize based on the new
   # grammar.


Select the text while inserting.

Select the text while inserting.

--- src/editor.coffee
+++ src/editor.coffee
@@ -702,17 +702,13 @@
       cursorView = @getCursorView()
       @hiddenInput.offset(cursorView.offset()) if cursorView.is(':visible')

-    startScreenPosition = null
     @hiddenInput.on 'compositionstart', =>
-      startScreenPosition = @getCursorScreenPosition()
       @hiddenInput.css('width', '100%')
     @hiddenInput.on 'compositionupdate', (e) =>
-      @insertText(e.originalEvent.data)
-      @selectToScreenPosition(startScreenPosition)
+      @insertText(e.originalEvent.data, select: true)
     @hiddenInput.on 'compositionend', =>
       @delete()
       @hiddenInput.css('width', '1px')
-      startScreenPosition = null

   selectOnMousemoveUntilMouseup: ->
     lastMoveEvent = null


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/engine.coffee
+++ src/engine.coffee
@@ -102,7 +102,12 @@
   ###

   Engine = (I={}) ->
-    Object.reverseMerge I, defaults
+    Object.reverseMerge I,
+      FPS:
+      age: 0
+      paused: false
+      showFPS: false
+      zSort: false

     frameAdvance = false


Defaulting to sprite dimensions if box parameters not explicitly specified

--- src/entity.coffee
+++ src/entity.coffee
@@ -51,6 +51,9 @@
     @speed   = opts.speed   || 0
     @facing  = opts.facing  || ''

+    @sprite     = new Image()
+    @sprite.src = opts.sprite || null
+
     @position =
       x: opts.x || 0
       y: opts.y || 0
@@ -63,8 +66,11 @@
       width:  opts.width  || 0
       height: opts.height || 0

-    @sprite     = new Image()
-    @sprite.src = opts.sprite || null
+    parent = @
+    @sprite.onload = ->
+      parent.box.width  = @width  if parent.box.width  == 0
+      parent.box.height = @height if parent.box.height == 0
+
     @animations       = []
     @currentAnimation = null


Nix arguments

Nix arguments

--- src/gutter.coffee
+++ src/gutter.coffee
@@ -73,8 +73,6 @@
   # is invalidated, or is destroyed, the decoration will be updated to reflect
   # the marker's state.
   #
-  # ## Arguments
-  #
   # * `marker` A {Marker} you want this decoration to follow.
   # * `decorationParams` An {Object} representing the decoration
   #   * `class` This CSS class will be applied to the decorated line number.


remove todo

remove todo

--- src/hinoki.coffee
+++ src/hinoki.coffee
@@ -34,7 +34,6 @@
   hinoki.getOne = (containers, nameOrPath, debug) ->
     path = hinoki.castPath nameOrPath

-    # TODO rename to resolved
     result = hinoki.resolveInContainers containers, path, debug

     unless result?


Deprecate non-compliant functions

Deprecate non-compliant functions

--- src/ipaddr.coffee
+++ src/ipaddr.coffee
@@ -216,6 +216,8 @@

   # Returns the address in compact, human-readable format like
   # 2001:db8:8:66::1
+  #
+  # Deprecated: use toRFC5952String() instead.
   toString: ->
     # Replace the first sequence of 1 or more '0' parts with '::'
     return @toNormalizedString().replace( /((^|:)(0(:|$))+)/, '::' )
@@ -246,6 +248,8 @@

   # Returns the address in expanded format with all zeroes included, like
   # 2001:db8:8:66:0:0:0:1
+  #
+  # Deprecated: use toFixedLengthString() instead.
   toNormalizedString: ->
     addr = (part.toString(16) for part in @parts).join ":"


Fix child for level

Fix child for level

--- src/layout.coffee
+++ src/layout.coffee
@@ -26,9 +26,10 @@
 #     <-- state...

 exports.layout = (game_dict) ->
-  level_dict = game_dict[my.key.children]
+  level_dict = game_dict[my.key.children][0]
+  console.log "!! layout level_dict", level_dict
   level_dict._CHILDREN = [
-    #header(level_dict)
+    header(level_dict)
     #controls(level_dict)
     #grid(level_dict)
     # sprites?


* minor changes

* minor changes

--- src/object.coffee
+++ src/object.coffee
@@ -8,7 +8,6 @@
 inheritsObject  = require 'inherits-ex/lib/inheritsObject'
 ObjectValue     = require './value/object'
 module.exports  = Type = require './type-info'
-

 register  = Type.register
 aliases   = Type.aliases
@@ -31,10 +30,11 @@
       aOptions = null
     else if aOptions.type
       vType = aOptions.type
-      if Object.keys(aOptions).length > 1
-        vType = Type.create(vType, aOptions)
-      else
-        vType = Type(vType)
+      vType = Type(vType)
+      #if Object.keys(aOptions).length > 1
+      #  vType = Type.create(vType, aOptions)
+      #else
+      #  vType = Type(vType)
       throw TypeError('no such type registered:'+aOptions.type) unless vType
     else
       vType = ObjectType.defaultType


Start of serializer.write Docco.

Start of serializer.write Docco.

--- src/packet.coffee
+++ src/packet.coffee
@@ -116,7 +116,7 @@
     if @pattern[@patternIndex].arrayed
       @fields.push([])

-##### packet.read(buffer[, offset][, length])
+##### parser.read(buffer[, offset][, length])
 # The `read` method reads from the buffer, returning when the current pattern is
 # read, or the end of the buffer is reached.

@@ -241,9 +241,17 @@

     @next(shiftable[0])

+##### serializer.write(buffer[, offset][, length])
+# The `write` method writes to the buffer, returning when the current pattern is
+# written, or the end of the buffer is reached.
+
+  # Write to the `buffer` in the region defined by the given `offset` and `length`.
   write: (buffer, offset, length) ->
     offset or= 0
     length or= buffer.length
+
+    # We set the pattern to null when all the fields have been written, so while
+    # there is a pattern to fill and space to write.
     while @pattern and offset < length
       if @pattern[@patternIndex].unpacked
         loop


<tests> Removing useless logs.

<tests> Removing useless logs.

--- tests/controllers/driver.coffee
+++ tests/controllers/driver.coffee
@@ -158,7 +158,6 @@
     #         @client.sendFile "drivers", driver.file, done

     #     it 'should reply with the created Driver', ->
-    #         console.log "DRIVER - POST REP: " + @body
     #         @body = JSON.parse @body
     #         expect(@err).to.not.exist
     #         expect(@response.statusCode).to.equal 201


Update import after moving file

Update import after moving file

--- tests/helpers/acceptance.coffee
+++ tests/helpers/acceptance.coffee
@@ -1,4 +1,4 @@
-`import startApp from '../helpers/start-app';`
+`import startApp from './start-app';`

 acceptance = (suiteName) ->
   App = null


sync: rm TODO note

sync: rm TODO note

--- src/sync.coffee
+++ src/sync.coffee
@@ -85,7 +85,6 @@

     writeResults: (t, results, cb) ->
         async.forEach results, (item, cb2) =>
-            # TODO: author?
             t.writeItem @node, item.id, item.el, cb2
         , cb


adding int_div edge case

adding int_div edge case

--- src/util.coffee
+++ src/util.coffee
@@ -39,10 +39,11 @@

 root.int_div = (rs, a, b) ->
   java_throw rs, 'java/lang/ArithmeticException', '/ by zero' if b == 0
-  towards_zero a / b
-  # TODO spec: "if the dividend is the negative integer of largest possible magnitude
+  # spec: "if the dividend is the negative integer of largest possible magnitude
   # for the int type, and the divisor is -1, then overflow occurs, and the
   # result is equal to the dividend."
+  return a if a == root.INT_MIN and b == -1
+  towards_zero a / b

 root.long_mod = (rs, a, b) ->
   java_throw rs, 'java/lang/ArithmeticException', '/ by zero' if b.isZero()


* closure_compile_with_sandbox_cache - fix browser mode problems

  - app.coffee tests pass
  - consolidate.js tests pass

--- src/view.coffee
+++ src/view.coffee
@@ -28,8 +28,9 @@
   ###
   __ = "  "
   """
-#{__}if not toffee?            then toffee = {}
-#{__}if not toffee.templates   then toffee.templates = {}
+
+#{__}if not toffee? then toffee = {}
+#{__}if not toffee.templates then toffee.templates = {}
 #{__}
 #{__}toffee.states = #{JSON.stringify states}
 #{__}
@@ -80,6 +81,7 @@
   ###
   __ = "  "
   """
+# keep this, for proper indenting
 #{__}toffee.__print = (locals, o) ->
 #{__}  if locals.__toffee.state is toffee.states.COFFEE
 #{__}    locals.__toffee.out.push o
@@ -268,7 +270,10 @@
       if not @error
         d = Date.now()
         try
-          @javaScript = coffee.compile c, {bare: true}
+          opts = { bare: true }
+          if @browserMode
+            opts.bare = false
+          @javaScript = coffee.compile c, opts
         catch e
           @error = new toffeeError @, errorTypes.COFFEE_COMPILE, e
         if @minimize and not @error
@@ -486,8 +491,7 @@
     ___  = @_tabAsSpaces()
     __ = "  "
     """
-_TMPL_ = (__toffee_run_input) ->
-#{if @browserMode then '' else getCommonHeaders false, @autoEscape }
+#{if @browserMode then '' else ('_TMPL_ = (__toffee_run_input) ->' + (getCommonHeaders false, @autoEscape)) }
 #{__}tmpl = toffee.templates["#{@bundlePath}"]  =
 #{__}  bundlePath: "#{@bundlePath}"
 #{__}tmpl.render = tmpl.pub = (__locals) ->


Add revision build parameter

Add revision build parameter

Signed-off-by: 47930cacb4784e3ef656356c2cdf2985a791ae49@intel.com

--- buildbot_travis/ui/src/app/configEditors/deploy_latest_dialog.controller.coffee
+++ buildbot_travis/ui/src/app/configEditors/deploy_latest_dialog.controller.coffee
@@ -38,7 +38,7 @@
                     field.errors = ''
                     if field.fields?
                         gatherFields(field.fields)
-                    else
+                    else
                         if field.fullName.match(/revision/)
                             params[field.fullName] = commit
                         else if field.fullName == 'stage'