Remove old commented out implementation of parser

--- app/assets/javascripts/player/vt.js.coffee
+++ app/assets/javascripts/player/vt.js.coffee
@@ -5,7 +5,6 @@
     @data = ''
     @resetTerminal()
     @render()
-    # @compilePatterns()

   handleData: (data) ->
     if data.match(/^\x1b[\x00-\x1f]/)
@@ -90,7 +89,6 @@
         @setHorizontalTabStop() # "H"
       when "\x8d"
         @reverseIndex() # "M"
-

   handlePrintableCharacters: (text) ->
     @buffer.print text
@@ -197,9 +195,6 @@
         @reportRowAndColumn()
       when "r" # Set top and bottom margins (scroll region on VT100)
         @setScrollRegion n or 0, m or @lines - 1
-      else
-        throw "no handler for CSI term: " + term
-

   handlePrivateControlSequence: (data, params) ->
     action = data[data.length - 1]
@@ -225,8 +220,6 @@
           # Clear screen, switch to normal screen buffer, and restore cursor position.
           @clearScreen()
           @switchToNormalBuffer()
-      # else
-      #   throw "unknown mode: " + mode + action

   parseParams: (params) ->
     if params.length is 0
@@ -236,243 +229,6 @@

     numbers

-#   _C0_PATTERNS:
-#     default: (data) ->
-#       console.log "no handler for: #{@formattedData(data)}"
-
-#     # C0 set of 7-bit control characters
-#     "\x1b?[\x00-\x1f]":
-#       # bell
-#       "\x07": (data) -> @bell()
-
-#       # backspace
-#       "\x08": (data) -> @backspace()
-
-#       # Move the cursor to the next tab stop
-#       "\x09": (data) ->
-
-#       "\x0a": (data) -> @lineFeed()
-
-#       "\x0d": (data) -> @carriageReturn()
-
-#       "\x0e": (data) ->
-
-#       "\x0f": (data) ->
-
-#       # Reserved (?)
-#       "\x82": (data) ->
-
-#       # Cancel Character, ignore previous character
-#       "\x94": (data) ->
-
-#       # # Escape sequence
-#       # "\x1b": _.extend({}, @_C0_PATTERNS, {
-
-#       # Control sequence
-#       "\x1b\\[": @_CS_PATTERNS
-
-#   _CS_PATTERNS:
-#     "sth": 1
-
-#   _PATTERNS: _.extend({}, @_C0_PATTERNS, {
-#     # Printable characters
-#     "([\x20-\x7e])+": @handlePrintableCharacters
-
-#     # "Delete", always and everywhere ignored
-#     "[\x7f\xff]": @noop
-
-#     # C1 control set
-#     "[\x80-\x9f]":
-
-#       # Control sequence
-#       "\x9b": @_CS_PATTERNS
-
-#     # G1 Displayable, 94 additional displayable characters
-#     "[\xa1-\xfe]": @handlePrintableCharacters
-
-#     # Always and everywhere a blank space
-#     "\xa0": -> @handlePrintableCharacters(' ')
-
-#   })
-
-  # PATTERNS:
-    # "\x00": (data) ->
-    # "\x07": (data) -> @bell()
-    # "\x08": (data) -> @backspace()
-    # "\x09": (data) -> @buffer.goToNextHorizontalTabStop()
-    # "\x0a": (data) -> @lineFeed()
-    # "\x0b": (data) -> @verticalTab()
-    # "\x0c": (data) -> @formFeed()
-    # "\x0d": (data) -> @carriageReturn()
-    # "\x0e": (data) ->
-    # "\x0f": (data) ->
-
-    # # 20 - 7e
-    # "([\x20-\x7e]|\xe2..|[\xc2\xc4\xc5].)+": (data, match) ->
-    #   @buffer.print match[0]
-
-    # "\x1b\\(B": (data) -> # SCS (Set G0 Character SET)
-
-    # "\x1b\\[([0-9;]*)([\x40-\x7e])": (data, match) ->
-    #   if match[1].length == 0
-    #     @params = []
-    #   else
-    #     @params = _(match[1].split(';')).map (n) -> if n is '' then undefined else parseInt(n)
-
-    #   @n = @params[0]
-    #   @m = @params[1]
-    #   @handleCS match[2]
-
-#     # private standards
-#     "\x1b\\[\\?([\x30-\x3f]+)([hlsr])": (data, match) ->
-#       # h = Sets DEC/xterm specific mode (http://ttssh2.sourceforge.jp/manual/en/about/ctrlseq.html#decmode)
-#       # l = Resets mode (http://ttssh2.sourceforge.jp/manual/en/about/ctrlseq.html#mode)
-#       # 1001 + s = ?
-#       # 1001 + r = ?
-#       modes = match[1].split(";")
-#       action = match[2]
-#       mode = undefined
-
-#       for mode in modes
-#         if mode is "1"
-#           # 1 + h / l = cursor keys stuff
-#         else if mode is "5"
-#           # Reverse/normal video - ignoring
-#         else if mode is "7"
-#           # Enables/disables autowrap mode
-#         else if mode is "12"
-#           if action is "h"
-#             # blinking cursor
-#           else action is "l"
-#             # steady cursor
-#         else if mode is "25"
-#           if action is "h"
-#             @showCursor()
-#           else if action is "l"
-#             @hideCursor()
-#         else if mode is "47"
-#           if action is "h"
-#             @switchToAlternateBuffer()
-#           else if action is "l"
-#             @switchToNormalBuffer()
-#         else if mode is "1000"
-#           # Enables/disables normal mouse tracking
-#         else if mode is "1001"
-#           # pbly sth with mouse/keys...
-#         else if mode is "1002"
-#           # 2002 + h / l = mouse tracking stuff
-#         else if mode is "1049"
-#           if action is "h"
-#             # Save cursor position, switch to alternate screen buffer, and clear screen.
-#             @switchToAlternateBuffer()
-#             @clearScreen()
-#           else if action is "l"
-#             # Clear screen, switch to normal screen buffer, and restore cursor position.
-#             @clearScreen()
-#             @switchToNormalBuffer()
-#         else
-#           throw "unknown mode: " + mode + action
-
-    # "\x1b\x3d": (data) -> # DECKPAM - Set keypad to applications mode (ESCape instead of digits)
-
-    # "\x1b\x3e": (data) -> # DECKPNM - Set keypad to numeric mode (digits intead of ESCape seq)
-
-    # "\x1b\\\\": -> # String Terminator (VT125 exits graphics)
-
-    # "\x1b\x5d[012]\x3b.*?\x07": (data, match) -> # OSC - Operating System Command (terminal title)
-
-    # "\x1b\\[>c": (data) -> # Secondary Device Attribute request (?)
-
-    # "\x1bc": -> @resetTerminal()
-    # "\x1bP([^\\\\])*?\\\\": (data) -> # DCS, Device Control String
-    # "\x1bD": -> @index()
-    # "\x1bE": -> @newLine()
-    # "\x1bH": -> @setHorizontalTabStop()
-    # "\x1bM": -> @reverseIndex()
-    # "\x1bk": -> # NAPLPS lock-shift G1 to GR
-
-    # "\x1b7": (data) -> # save cursor pos and char attrs
-    #   @saveTerminalState()
-
-    # "\x1b8": (data) -> # restore cursor pos and char attrs
-    #   @restoreTerminalState()
-
-  # handleCS: (term) ->
-  #   switch term
-  #     when "@"
-  #       @buffer.insertCharacters @n
-  #     when "A"
-  #       @buffer.priorRow @n
-  #     when "B"
-  #       @buffer.nextRow @n
-  #     when "C"
-  #       @buffer.nextColumn @n
-  #     when "D"
-  #       @buffer.priorColumn @n
-  #     when "E"
-  #       @buffer.nextRowFirstColumn @n
-  #     when "F"
-  #       @buffer.priorRowFirstColumn @n
-  #     when "G"
-  #       @buffer.goToColumn @n
-  #     when "H"
-  #       @buffer.goToRowAndColumn @n, @m
-  #     when "I"
-  #       @buffer.goToNextHorizontalTabStop @n
-  #     when "J"
-  #       if @n is 2
-  #         @buffer.eraseScreen()
-  #       else if @n is 1
-  #         @buffer.eraseFromScreenStart()
-  #       else
-  #         @buffer.eraseToScreenEnd()
-  #     when "K"
-  #       if @n is 2
-  #         @buffer.eraseRow()
-  #       else if @n is 1
-  #         @buffer.eraseFromRowStart()
-  #       else
-  #         @buffer.eraseToRowEnd()
-  #     when "L"
-  #       @buffer.insertLine @n or 1
-  #     when "M"
-  #       @buffer.deleteLine @n or 1
-  #     when "P" # DCH - Delete Character, from current position to end of field
-  #       @buffer.deleteCharacters @n or 1
-  #     when "S"
-  #       @buffer.scrollUp @n
-  #     when "T"
-  #       @buffer.scrollDown @n
-  #     when "X"
-  #       @buffer.eraseCharacters @n
-  #     when "Z"
-  #       @buffer.goToPriorHorizontalTabStop @n
-  #     when "b"
-  #       @buffer.repeatLastCharacter @n
-  #     when "d" # VPA - Vertical Position Absolute
-  #       @buffer.goToRow @n
-  #     when "f"
-  #       @buffer.goToRowAndColumn @n, @m
-  #     when "g"
-  #       if !@n or @n is 0
-  #         @buffer.clearHorizontalTabStop()
-  #       else if @n is 3
-  #         @buffer.clearAllHorizontalTabStops()
-  #     when "l" # l, Reset mode
-  #       console.log "(TODO) reset: " + @n
-  #     when "m"
-  #       @handleSGR @params
-  #     when "n"
-  #       @reportRowAndColumn()
-  #     when "r" # Set top and bottom margins (scroll region on VT100)
-  #       @setScrollRegion @n or 0, @m or @lines - 1
-  #     when "^"
-  #       # reserved
-  #       # Privacy Message (password verification), terminated by ST
-  #       # TODO
-  #     else
-  #       throw "no handler for CSI term: " + term
-
   handleSGR: (numbers) ->
     @buffer.setBrush @sgrInterpreter.buildBrush(@buffer.brush, numbers)

@@ -480,9 +236,6 @@
     @view.visualBell()
     # @trigger('bell')

-  # compilePatterns: ->
-  #   @COMPILED_PATTERNS = ([new RegExp("^" + re), f] for re, f of @PATTERNS)
-
   feed: (data) ->
     @data += data

@@ -492,32 +245,12 @@
       if processed is 0
         # console.log "no kurwa: #{@formattedData(@data)}"
         break
-        # throw 'up'

       @data = @data.slice(processed)

-      # match = null
-
-      # for pattern in @COMPILED_PATTERNS
-      #   match = pattern[0].exec(@data)
-
-      #   if match
-      #     handler = pattern[1]
-      #     handler.call(this, @data, match)
-      #     @data = @data.slice(match[0].length)
-      #     break
-
-      # break unless match
-
     @render()

     @data.length is 0
-
-  # aaa: ->
-  #   if @data.length > 500
-  #     head = @data.slice(0, 100)
-  #     hex = ("0x#{c.charCodeAt(0).toString(16)}" for c in head)
-  #     console.log "failed matching: '" + Utf8.decode(head) + "' (" + hex.join() + ")" # [pos: " + (@dataIndex - count) + "]"

   formattedData: (data) ->
     head = data.slice(0, 100)


Comment

Comment

--- app/assets/javascripts/player/vt.js.coffee
+++ app/assets/javascripts/player/vt.js.coffee
@@ -119,7 +119,7 @@
         if mode is "1"
           # 1 + h / l = cursor keys stuff
         else if mode is "5"
-          # Reverse/normal video
+          # Reverse/normal video - ignoring
         else if mode is "7"
           # Enables/disables autowrap mode
         else if mode is "12"


[Server][auto_refresh] add class for managing connection

error: pathspec 'lib/Epuber/server/auto_refresh/connector.coffee' did not match any file(s) known to git

--- lib/Epuber/server/auto_refresh/connector.coffee
+++ lib/Epuber/server/auto_refresh/connector.coffee
@@ -0,0 +1,105 @@
+{ Parser, PROTOCOL_6, PROTOCOL_7 } = require './protocol'
+
+Version = '2.2.2'
+
+exports.Connector = class Connector
+
+    constructor: (@options, @WebSocket, @Timer, @handlers) ->
+        @_uri = "ws#{if @options.https then "s" else ""}://#{@options.host}:#{@options.port}/livereload"
+
+        @_nextDelay = @options.mindelay
+        @_connectionDesired = no
+        @protocol = 0
+
+        @protocolParser = new Parser
+            connected: (@protocol) =>
+                @_handshakeTimeout.stop()
+                @_nextDelay = @options.mindelay
+                @_disconnectionReason = 'broken'
+                @handlers.connected(protocol)
+            error: (e) =>
+                @handlers.error(e)
+                @_closeOnError()
+            message: (message) =>
+                @handlers.message(message)
+
+        @_handshakeTimeout = new Timer =>
+            return unless @_isSocketConnected()
+            @_disconnectionReason = 'handshake-timeout'
+            @socket.close()
+
+        @_reconnectTimer = new Timer =>
+            return unless @_connectionDesired  # shouldn't hit this, but just in case
+            @connect()
+
+        @connect()
+
+
+    _isSocketConnected: ->
+        @socket and @socket.readyState is @WebSocket.OPEN
+
+    connect: ->
+        @_connectionDesired = yes
+        return if @_isSocketConnected()
+
+        # prepare for a new connection
+        @_reconnectTimer.stop()
+        @_disconnectionReason = 'cannot-connect'
+        @protocolParser.reset()
+
+        @handlers.connecting()
+
+        @socket = new @WebSocket(@_uri)
+        @socket.onopen    = (e) => @_onopen(e)
+        @socket.onclose   = (e) => @_onclose(e)
+        @socket.onmessage = (e) => @_onmessage(e)
+        @socket.onerror   = (e) => @_onerror(e)
+
+    disconnect: ->
+        @_connectionDesired = no
+        @_reconnectTimer.stop()   # in case it was running
+        return unless @_isSocketConnected()
+        @_disconnectionReason = 'manual'
+        @socket.close()
+
+
+    _scheduleReconnection: ->
+        return unless @_connectionDesired  # don't reconnect after manual disconnection
+        unless @_reconnectTimer.running
+            @_reconnectTimer.start(@_nextDelay)
+            @_nextDelay = Math.min(@options.maxdelay, @_nextDelay * 2)
+
+    sendCommand: (command) ->
+        return unless @protocol?
+        @_sendCommand command
+
+    _sendCommand: (command) ->
+        @socket.send JSON.stringify(command)
+
+    _closeOnError: ->
+        @_handshakeTimeout.stop()
+        @_disconnectionReason = 'error'
+        @socket.close()
+
+    _onopen: (e) ->
+        @handlers.socketConnected()
+        @_disconnectionReason = 'handshake-failed'
+
+        # start handshake
+        hello = { command: 'hello', protocols: [PROTOCOL_6, PROTOCOL_7] }
+        hello.ver     = Version
+        hello.ext     = @options.ext     if @options.ext
+        hello.extver  = @options.extver  if @options.extver
+        hello.snipver = @options.snipver if @options.snipver
+        @_sendCommand hello
+        @_handshakeTimeout.start(@options.handshake_timeout)
+
+    _onclose: (e) ->
+        @protocol = 0
+        @handlers.disconnected @_disconnectionReason, @_nextDelay
+        @_scheduleReconnection()
+
+    _onerror: (e) ->
+
+    _onmessage: (e) ->
+        @protocolParser.process(e.data)


Fix up the way ad manager detects ads.

Fix up the way ad manager detects ads.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lonelyplanet/rizzo.git/'


Remove console.log

Remove console.log

--- app/assets/javascripts/lib/text_utility.js.coffee
+++ app/assets/javascripts/lib/text_utility.js.coffee
@@ -32,8 +32,11 @@
     selObj = window.getSelection()
     selRange = selObj.getRangeAt(0)
     text = $textArea.val()
-    lineBreak = '\n' if textArea.selectionStart > 0
-    console.log(textArea.selectionStart,lineBreak)
+    if textArea.selectionStart > 0
+      lineBreak = '\n'
+    else
+      lineBreak = ''
+
     replaceWith = @replaceRange(
       text,
       textArea.selectionStart,
@@ -82,7 +85,6 @@
     $thisTextarea.val(latestUndo.newVal)

   gl.text.addListeners = () ->
-    console.log('addListeners')
     self = @
     $('.js-md').on 'click', ->
       $this = $(@)
@@ -119,7 +121,6 @@
             gl.text._previousState,
             $thisTextarea.val()
           )
-
       gl.text._previousState = $thisTextarea.val()

   gl.text.removeListeners = () ->


Set max height for drop down for groups.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/biola/announcement-publisher.git/'


and suppressing errors from the main startup process

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bubblegroup/bubblebot.git/'


[fix] [bot] settings defautl value on command

Also contains a minor refactoring for `isAdmin`

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Mikuia/Mikuia.git/'


started work on notification system

started work on notification system

error: pathspec 'src/controllers/notification_controller.coffee' did not match any file(s) known to git

--- src/controllers/notification_controller.coffee
+++ src/controllers/notification_controller.coffee
@@ -0,0 +1,48 @@
+
+# This is the in-memory map of notifications for sending out in real-time
+_pendingNotifications = {}
+_currentListeners = {}
+
+_pushNotification = (userId, notification) ->
+  if userId of _pendingNotifications
+    _pendingNotifications[userId].push notification
+  else
+    _pendingNotifications[userId] = [notification]
+
+  # Kill the timeout loop and send notification immediately if listening
+  if userId of _currentListeners
+    clearTimeout listenLoop
+    _listenLoopFunc()
+
+exports.new_message_for_user (message, userId) ->
+  # TODO Move this type constant somewhere
+  notification = {type: 'New Message', body: {message}}
+  _pushNotification userId, notification
+
+_notifyFunc = ->
+  for userId, notifications of _pendingNotifications
+    if userId of _currentListeners
+      for res in _currentListeners[userId]
+        try
+          res.send notifications
+        catch
+          # Listener stopped, run the unable to push notification routine
+      delete _currentListeners[userId]
+
+_listenLoopFunc = ->
+  _notifyFunc()
+  listenLoop = setTimeout ->
+    _listenLoopFunc()
+  , 10000 # TODO Move this constant
+
+exports.startNotificationServer = ->
+  _listenLoopFunc()
+
+exports.get_listen_notifications = (req, res) ->
+  # Put the response object in the listeners map
+  if req.user.id of _currentListeners
+    _currentListeners[req.user.id].push res
+  else
+    _currentListeners[req.user.id] = [res]
+
+


Add .editor class to react wrapper for package activation events

--- src/react-editor-view.coffee
+++ src/react-editor-view.coffee
@@ -7,7 +7,7 @@
 class ReactEditorView extends View
   # The `overlayer` class is included for backwards compatibility with
   # context menus. It should be removed in v1.0.0
-  @content: -> @div class: 'react-wrapper overlayer'
+  @content: -> @div class: 'editor react-wrapper overlayer'

   focusOnAttach: false


ApiGenerator: do not add bodyParam if there is a custom definition

--- scripts/api-generator.coffee
+++ scripts/api-generator.coffee
@@ -222,7 +222,8 @@

   for method, signatures of methods.instance

-    parameters = [ { $ref: '#/parameters/instanceParam' }, { $ref: '#/parameters/bodyParam' } ]
+    hasCustomParams = no
+    parameters = [{ $ref: '#/parameters/instanceParam' }]
     response = { description: 'OK', schema }
     if returns = docs[name]['instance'][method]?.returns
       if Object.keys(returns).length and swagger.definitions[returns.type]
@@ -241,8 +242,12 @@
             required: true
             description: 'body of the request'
           }
+          hasCustomParams = yes
         else if example.title is 'return'
           response.schema = example.schema
+
+    unless hasCustomParams
+      parameters.push { $ref: '#/parameters/bodyParam' }

     paths["/remote.api/#{name}.#{method}/{id}"] =
       post:


fix (Simulator) use stdout to get results from ios-sim

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/steroids.git/'


We have node now, so kill our path module

--- src/stdlib/path.coffee
+++ src/stdlib/path.coffee
@@ -1,15 +0,0 @@
-# node.js path module
-# http://nodejs.org/docs/v0.6.0/api/path.html
-
-_ = require 'underscore'
-
-module.exports =
-  # Return the last portion of a path. Similar to the Unix basename command.
-  basename: (filepath) ->
-    _.last filepath.split '/'
-
-  # Return the extension of the path, from the last '.' to end of string in
-  # the last portion of the path. If there is no '.' in the last portion of
-  # the path or the first character of it is '.', then it returns an empty string.
-  extname: (filepath) ->
-    _.last filepath.split '.'


add image for when somebody asks, "what the fuck?"

error: pathspec 'scripts/what-the-fuck.coffee' did not match any file(s) known to git

--- scripts/what-the-fuck.coffee
+++ scripts/what-the-fuck.coffee
@@ -0,0 +1,6 @@
+# What the fuck?
+#
+
+module.exports = (robot) ->
+  robot.hear /what the fuck(.*)/i, (msg) ->
+    msg.send "http://i49.tinypic.com/2vi191d.gif"


simplify keybinder and make it better. fixes overriding

--- src/stdlib/key-binder.coffee
+++ src/stdlib/key-binder.coffee
@@ -45,56 +45,40 @@
     keys.push event.charactersIgnoringModifiers.toLowerCase().charCodeAt 0

     binding = keys.sort().join "-"
-
-    for scope, bindings of @keymaps
-      break if method = bindings[binding]
-    return false if not method
-
     try
-      @triggerBinding scope, method
+      @triggerBinding binding
     catch error
       console.error "Failed to run binding #{@bindingFromAscii binding}."
       console.error error

-    true
+
+  # Given a keyboard combination, goes through the responder
+  # chain and checks if any object (or any of that object's super
+  # classes) respond to the binding.
+  #
+  # If so, it triggers the binding.
+  #
+  # binding - A String in the form of "#{charCode}-#{chardCode}"
+  #
+  # Returns true if we found and triggered the binding, false if not.
+  triggerBinding: (binding) ->
+    for responder in @responders()
+      name = responder.constructor.name?.toLowerCase()
+      name = 'window' if responder is window
+
+      if method = @keymaps[name]?[binding]
+        if _.isFunction method
+          method responder
+        else
+          responder[method]()
+        return true
+
+    false

   responders: ->
     extensions = _.select (_.values atom.extensions), (extension) ->
       extension.running?
     _.flatten [ extensions, window.resource.responder(), window, atom.app ]
-
-  triggerBinding: (scope, method) ->
-    responder = _.detect @responders(), (responder) =>
-      (scope is 'window' and responder is window) or
-        responder.constructor.name?.toLowerCase() is scope or
-        @inheritedKeymap responder, scope
-    if responder
-      if _.isFunction method
-        method responder
-      else
-        responder[method]()
-
-  # If you inherit from a class, you inherit its keymap.
-  #
-  # Example:
-  #   class GistEditor extends Editor
-  #
-  # Will respond to these bindings:
-  #   gisteditor:
-  #     'cmd+ctrl-g': 'createGist'
-  # And these:
-  #   editor:
-  #     'cmd-n': 'new'
-  #
-  # Returns a Boolean
-  inheritedKeymap: (responder, scope) ->
-    parent = responder.constructor.__super__
-    while parent?.constructor?.name
-      if parent.constructor.name.toLowerCase() is scope
-        return true
-      else
-        parent = parent.constructor.__super__
-    false

   bindingParser: (binding) ->
     keys = binding.trim().split '-'


getLaunchURL docs fixed, verified to work

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/supersonic.git/'


ajx requests merged

ajx requests merged

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


add darksky.coffee from hubot-scripts

add darksky.coffee from hubot-scripts

error: pathspec 'src/darksky.coffee' did not match any file(s) known to git

--- src/darksky.coffee
+++ src/darksky.coffee
@@ -0,0 +1,57 @@
+# Description
+#   Grabs the current forecast from Dark Sky
+#
+# Dependencies
+#   None
+#
+# Configuration
+#   HUBOT_DARK_SKY_API_KEY
+#   HUBOT_DARK_SKY_DEFAULT_LOCATION
+#   HUBOT_DARK_SKY_UNITS (optional - us, si, ca, or uk)
+#
+# Commands:
+#   hubot weather - Get the weather for HUBOT_DARK_SKY_DEFAULT_LOCATION
+#   hubot weather <location> - Get the weather for <location>
+#
+# Notes:
+#   If HUBOT_DARK_SKY_DEFAULT_LOCATION is blank, weather commands without a location will be ignored
+#
+# Author:
+#   kyleslattery
+module.exports = (robot) ->
+  robot.respond /weather ?(.+)?/i, (msg) ->
+    location = msg.match[1] || process.env.HUBOT_DARK_SKY_DEFAULT_LOCATION
+    return if not location
+
+    googleurl = "http://maps.googleapis.com/maps/api/geocode/json"
+    q = sensor: false, address: location
+    msg.http(googleurl)
+      .query(q)
+      .get() (err, res, body) ->
+        result = JSON.parse(body)
+
+        if result.results.length > 0
+          lat = result.results[0].geometry.location.lat
+          lng = result.results[0].geometry.location.lng
+          darkSkyMe msg, lat,lng , (darkSkyText) ->
+            response = "Weather for #{result.results[0].formatted_address}\n#{darkSkyText}"
+            msg.send response
+        else
+          msg.send "Couldn't find #{location}"
+
+darkSkyMe = (msg, lat, lng, cb) ->
+  url = "https://api.forecast.io/forecast/#{process.env.HUBOT_DARK_SKY_API_KEY}/#{lat},#{lng}/"
+  if process.env.HUBOT_DARK_SKY_UNITS
+    url += "?units=#{process.env.HUBOT_DARK_SKY_UNITS}"
+  msg.http(url)
+    .get() (err, res, body) ->
+      result = JSON.parse(body)
+
+      if result.error
+        cb "#{result.error}"
+        return
+
+      response = "Currently: #{result.currently.summary} (#{result.currently.temperature}°)"
+      response += "\nToday: #{result.hourly.summary}"
+      response += "\nComing week: #{result.daily.summary}"
+      cb response


Use atom directly to run package specs

Use atom directly to run package specs

--- tasks/spec-task.coffee
+++ tasks/spec-task.coffee
@@ -13,26 +13,40 @@
   runPackageSpecs = (callback) ->
     failedPackages = []
     rootDir = grunt.config.get('atom.shellAppDir')
-    appDir = grunt.config.get('atom.appDir')
-    atomPath = path.join(appDir, 'atom.sh')
-    apmPath = path.join(appDir, 'node_modules/.bin/apm')
+    contentsDir = grunt.config.get('atom.contentsDir')
+    resourcePath = process.cwd()
+    if process.platform is 'darwin'
+      appPath = path.join(contentsDir, 'MacOS', 'Atom')
+    else if process.platform is 'win32'
+      appPath = path.join(contentsDir, 'atom.exe')

     packageSpecQueue = async.queue (packagePath, callback) ->
-      options =
-        cmd: apmPath
-        args: ['test', '--path', atomPath]
-        opts:
-          cwd: packagePath
-          env: _.extend({}, process.env, ATOM_PATH: rootDir)
+      if process.platform is 'darwin'
+        options =
+          cmd: appPath
+          args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{path.join(packagePath, 'spec')}"]
+          opts:
+            cwd: packagePath
+            env: _.extend({}, process.env, ATOM_PATH: rootDir)
+      else if process.platform is 'win32'
+        options =
+          cmd: process.env.comspec
+          args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{path.join(packagePath, 'spec')}", "--log-file=ci.log"]
+          opts:
+            cwd: packagePath
+            env: _.extend({}, process.env, ATOM_PATH: rootDir)
+
       grunt.verbose.writeln "Launching #{path.basename(packagePath)} specs."
       spawn options, (error, results, code) ->
+        if process.platform is 'win32'
+          process.stdout.write(fs.readFileSync('ci.log'))
+          fs.unlinkSync('ci.log')

         failedPackages.push path.basename(packagePath) if error
         callback()

     modulesDirectory = path.resolve('node_modules')
     for packageDirectory in fs.readdirSync(modulesDirectory)
-      return callback(null, [])
       packagePath = path.join(modulesDirectory, packageDirectory)
       continue unless grunt.file.isDir(path.join(packagePath, 'spec'))
       continue unless isAtomPackage(packagePath)
@@ -57,11 +71,12 @@
     else if process.platform is 'win32'
       options =
         cmd: process.env.comspec
-        args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}", "--log-file=core.log"]
+        args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}", "--log-file=ci.log"]

     spawn options, (error, results, code) ->
-      process.stdout.write(fs.readFileSync('core.log'))
-      fs.unlinkSync('core.log')
+      if process.platform is 'win32'
+        process.stdout.write(fs.readFileSync('ci.log'))
+        fs.unlinkSync('ci.log')
       packageSpecQueue.concurrency = 2
       callback(null, error)


added logout handler test file

added logout handler test file

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Smoke test for making parser robust-ish

Smoke test for making parser robust-ish

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/obihann/drafter.js.git/'


on_error only called if defined and is a function

--- {{cookiecutter.app_name}}/{{cookiecutter.app_name}}/frontend/client/coffee/utils/backbone-ajax-jwt.coffee
+++ {{cookiecutter.app_name}}/{{cookiecutter.app_name}}/frontend/client/coffee/utils/backbone-ajax-jwt.coffee
@@ -37,7 +37,7 @@
     retry.error = (args...) ->
       console.log "error in retry ajax call"
       console.log "calling original error handler with retry"
-      on_error(args..., 'retry')
+      on_error?(args..., 'retry')
     $.ajax settings.url,
       type: 'POST'
       data: {}


Added latest local news script

Added latest local news script

error: pathspec 'scripts/local-news.coffee' did not match any file(s) known to git

--- scripts/local-news.coffee
+++ scripts/local-news.coffee
@@ -0,0 +1,57 @@
+# Description:
+#   Display latest news story from MEN topic page - http://www.manchestereveningnews.co.uk/all-about/manchester-central-reference-library?service=rss
+#
+# Dependencies:
+#   "request": "2.14.x",
+#   "feedparser": "0.16.x"
+#		"moment": "2.8.3"
+#
+# Configuration:
+#   None
+#
+# Commands:
+#   latest local news - Gets the latest story from MEN about the Manchester Central library.
+#
+# Author:
+#   robertocarroll
+
+FeedParser = require('feedparser')
+request = require('request')
+moment = require('moment')
+
+getTheArticle = (callback) ->
+  feedparser = new FeedParser()
+
+  req = request(
+    url: 'http://www.manchestereveningnews.co.uk/all-about/manchester-central-reference-library?service=rss'
+
+    headers:
+      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'
+  )
+
+  req.on('error', (error) ->
+    callback("Something bad happened with the request. #fufielding. #{error}")
+  )
+
+  req.on('response', (res) ->
+    return callback("bad response code - #{res.statusCode}") unless res.statusCode == 200
+    @pipe(feedparser)
+  )
+
+  feedparser.on('error', (error) ->
+    callback("Feedparser error - #{error}")
+  )
+
+  feedparser.on('readable', ->
+	  while item = @read()
+	  	for line in item.title.split(/<br *\/>/)
+        callback(line, item.link, moment(item.date, "ddd MMM DD YYYY HH:mm:ss ZZ").fromNow(true))
+  )
+
+module.exports = (robot) ->
+  robot.hear /latest local news ?/i, (msg) ->
+    gotItThanks = false
+
+    getTheArticle (article, theLink, theDate) ->
+      msg.send "Here's the latest news about me: '#{article}'. Find out more here: #{theLink}" unless gotItThanks
+      gotItThanks = true


Groups: Updated logo section in dashboard.


resurrection.teamwork: curry ActivityEditWidget cssClass option


Kite: Validate kite name in create kite modal.


Set custom header in ajax requests.

Set custom header in ajax requests.

--- core/htdocs_source/src/pods/openxpki/route.coffee
+++ core/htdocs_source/src/pods/openxpki/route.coffee
@@ -7,6 +7,10 @@
         limit:
             refreshModel: true

+    setupAjax: Em.on "init", ->
+        Em.$.ajaxSetup
+            beforeSend: (xhr) ->
+                xhr.setRequestHeader "X-OPENXPKI-Client", "1"

     needReboot: [ "login", "logout", "welcome" ]

@@ -62,7 +66,7 @@
             else
                 target = "top"

-        $.ajax(req).then (doc) =>
+        Em.$.ajax(req).then (doc) =>
             source.beginPropertyChanges()

             source.set "status", doc.status


Start with empty editor

Start with empty editor

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/samestep/env.git/'


Send sms via the 46elks.com api

Send sms via the 46elks.com api

error: pathspec 'src/scripts/46elks.coffee' did not match any file(s) known to git

--- src/scripts/46elks.coffee
+++ src/scripts/46elks.coffee
@@ -0,0 +1,89 @@
+# Allows Hubot to send text messages using 46elks.com API.
+#
+# you need to set HUBOT_46ELKS_USERNAME and HUBOT_46ELKS_PASSWORD
+#
+# sms <user> <message> - Sends <message> to the number <to>.
+# <user> has phone number <phone> - Sets the phone number of <user> to <phone>.
+# give me the phone number to <user> - Gets the phone number of <user>.e
+
+QS      = require "querystring"
+module.exports = (robot) ->
+
+  getAmbiguousUserText = (users) ->
+    "Be more specific, I know #{users.length} people named like that: #{(user.name for user in users).join(", ")}"
+
+  robot.respond /sms (\w+) (.*)/i, (msg) ->
+    to    = msg.match[1]
+    bahdy = msg.match[2] # bahdy, that's how john mayer would say it.
+    user  = process.env.HUBOT_46ELKS_USERNAME
+    pass  = process.env.HUBOT_46ELKS_PASSWORD
+    from  = "Hubot"
+    auth  = 'Basic ' + new Buffer(user + ':' + pass).toString("base64")
+
+    unless user
+      msg.send "46Elks USERNAME isn't set."
+      msg.send "Please set the HUBOT_46ELKS_USERNAME environment variable."
+      return
+
+    unless pass
+      msg.send "46Elks PASSWORD isn't set."
+      msg.send "Please set the HUBOT_46ELKS_PASSWORD environment variable."
+      return
+
+    #get <user>'s phone number as listed in the brain
+    if user = robot.userForName(to)
+      if user.phone == ""
+        msg.send user.name + ' has no phone! set it with <user> has phone <phone>'
+        return
+      else
+        to = user.phone
+        to = to.toString().replace(/\d/, '+46')
+    else
+      msg.send 'Me cant find ' + to + ', are you sure that person is born?'
+      return
+
+    data  = QS.stringify from: from, to: to, message: bahdy
+
+    msg.http("https://api.46elks.com")
+      .path("/a1/SMS")
+      .header("Authorization", auth)
+      .post(data) (err, res, body) ->
+        switch res.statusCode
+          when 200
+            msg.send "Sent sms to #{user.name}"
+          else
+            msg.send "Failed to send."
+
+  robot.respond /@?([\w .-_]+) has phone number (\d*)*$/i, (msg) ->
+    name  = msg.match[1]
+    phone = msg.match[2].trim()
+
+
+    users = robot.usersForFuzzyName(name)
+    if users.length is 1
+      user = users[0]
+      if user.phone == phone
+        msg.send "I know."
+      else
+        user.phone = phone
+        msg.send "Ok, #{name} has phone #{phone}."
+    else if users.length > 1
+      msg.send getAmbiguousUserText users
+    else
+      msg.send "I don't know anything about #{name}."
+
+
+
+  robot.respond /@?give me the phone number to ([\w .-_]+)*/i, (msg) ->
+    name  = msg.match[1]
+    users = robot.usersForFuzzyName(name)
+    if users.length is 1
+      user = users[0]
+      if user.phone.length < 1
+        msg.send "#{user.name} has no phone, set it first!"
+      else
+        msg.send "#{user.name} has phone number #{user.phone}."
+    else if users.length > 1
+      msg.send getAmbiguousUserText users
+    else
+      msg.send "I don't know anything about #{name}."


Added gitlab script

Added gitlab script

error: pathspec 'src/scripts/gitlab.coffee' did not match any file(s) known to git

--- src/scripts/gitlab.coffee
+++ src/scripts/gitlab.coffee
@@ -0,0 +1,79 @@
+# Description:
+#   Post gitlab related events using gitlab hooks to IRC
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   GITLAB_CHANNEL
+#
+# Commands:
+#   None
+#
+# URLS:
+#   /gitlab/system
+#   /gitlab/web
+#
+# Dependencies:
+#   "querystring" : "0.1.0"
+#
+# Author:
+#   omribahumi
+
+querystring = require 'querystring'
+
+module.exports = (robot) ->
+  gitlabChannel = process.env.GITLAB_CHANNEL or "#gitlab"
+
+  bold = (text) ->
+    "\x02" + text + "\x02"
+  underline = (text) ->
+    "\x1f" + text + "\x1f"
+
+  trim_commit_url = (url) ->
+    url.replace(/(\/[0-9a-f]{9})[0-9a-f]+$/, '$1')
+
+  handler = (type, req, res) ->
+    parameters = querystring.parse(req._parsedUrl.query)
+    hook = req.body
+
+    targets = if parameters.targets then gitlabChannel + ',' + parameters.targets else gitlabChannel
+    switch type
+      when "system"
+        switch hook.event_name
+          when "project_create"
+            robot.send room: targets, "Yay! New gitlab project #{bold(hook.name)} created by #{bold(hook.owner_name)} (#{bold(hook.owner_email)})"
+          when "project_destroy"
+            robot.send room: targets, "Oh no! #{bold(hook.owner_name)} (#{bold(hook.owner_email)}) deleted the #{bold(hook.name)} project"
+          when "user_add_to_team"
+            robot.send room: targets, "#{bold(hook.project_access)} access granted to #{bold(hook.user_name)} (#{bold(hook.user_email)}) on #{bold(hook.project_name)} project"
+          when "user_remove_from_team"
+            robot.send room: targets, "#{bold(hook.project_access)} access revoked from #{bold(hook.user_name)} (#{bold(hook.user_email)}) on #{bold(hook.project_name)} project"
+          when "user_create"
+            robot.send room: targets, "Please welcome #{bold(hook.name)} (#{bold(hook.email)}) to Gitlab!"
+          when "user_destroy"
+            robot.send room: targets, "We will be missing #{bold(hook.name)} (#{bold(hook.email)}) on Gitlab"
+      when "web"
+        message = []
+        branch = hook.ref.split("/")[2..].join("/")
+        # if the ref before the commit is 00000, this is a new branch
+        if /^0+$/.test(hook.before)
+            message.push "Gitlab #{bold(hook.repository.name)} (#{underline(hook.repository.url)}): #{bold(hook.user_name)} pushed a new branch: #{bold(branch)}"
+        else
+            message.push "Gitlab #{bold(hook.repository.name)} (#{underline(hook.repository.url)}): #{bold(hook.user_name)} pushed #{bold(hook.total_commits_count)} commits to #{bold(branch)}:"
+            for i, commit of hook.commits
+              commit_message = commit.message.split("\n")[0]
+              message.push "    * #{commit_message} (#{underline(trim_commit_url(commit.url))})"
+            if hook.total_commits_count > 1
+                message.push "Entire diff: #{underline(hook.repository.url + '/compare/' + hook.before.substr(0,9) + '...' + hook.after.substr(0,9))}"
+        message = message.join("\n")
+        robot.send room: targets, message
+
+  robot.router.post "/gitlab/system", (req, res) ->
+    handler "system", req, res
+    res.end ""
+
+  robot.router.post "/gitlab/web", (req, res) ->
+    handler "web", req, res
+    res.end ""
+


First commit of projects rewrite with React

error: pathspec 'salvus/page/projects.cjsx' did not match any file(s) known to git

--- salvus/page/projects.cjsx
+++ salvus/page/projects.cjsx
@@ -0,0 +1,639 @@
+{salvus_client} = require('salvus_client')
+{project_page}  = require('project')
+{top_navbar}    = require('top_navbar')
+{React, Actions, Store, flux, rtypes, rclass, FluxComponent}  = require('flux')
+_ = require('underscore')
+misc = require('misc')
+{required, defaults} = misc
+{html_to_text} = require('misc_page')
+{Row, Col, Well, Button, ButtonGroup, Grid, Input} = require('react-bootstrap')
+{Icon} = require('r_misc')
+TimeAgo = require('react-timeago')
+
+exports.cached_function = cached_function = (f) ->
+    cache = {}
+    g = (args...) ->
+        key = misc.hash_string(JSON.stringify(args))
+        a = cache[key]
+        if a?
+            return a
+        else
+            a = f(args...)
+            cache[key] = a
+            return a
+    g.clear_cache = () -> cache = {}
+    return g
+###
+# Projects
+###
+
+# Define projects actions
+class ProjectsActions extends Actions
+    setTo: (settings) ->
+        settings : settings
+
+# Register projects actions
+flux.createActions('projects', ProjectsActions)
+
+# Define projects store
+class ProjectsStore extends Store
+    constructor: (flux) ->
+        super()
+        ActionIds = flux.getActionIds('projects')
+        @register(ActionIds.setTo, @setTo)
+        @state = {}
+
+    setTo: (message) ->
+        @setState(message.settings)
+
+# Register projects store
+flux.createStore('projects', ProjectsStore, flux)
+
+store = flux.getStore('projects')
+
+find_text = (search, hashtags) ->
+    query = search.toLowerCase()
+    for tag, selected of hashtags
+        if selected
+            query += " #" + tag
+    query
+
+exports.get_project_info = (opts) ->
+    opts = defaults opts,
+        project_id : required
+        cb         : required
+    project = opts.project_id
+    if store.state.project_list?
+        for p in store.state.project_list
+            if p.project_id == project
+                opts.cb(undefined, p)
+                return
+    if store.state.hidden_project_list?
+        for p in store.state.hidden_project_list
+            if p.project_id == project
+                opts.cb(undefined, p)
+                return
+    # have to get info from database.
+    salvus_client.project_info
+        project_id : project
+        cb         : opts.cb
+
+# Return last downloaded project list
+exports.get_project_list = (opts) ->
+    opts = defaults opts,
+        update   : false      # if false used cached local version if available,
+                              # though it may be out of date
+        hidden   : false      # whether to list hidden projects (if false don't list any hidden projects; if true list only hidden projects)
+        select   : undefined  # if given, populate with selectable list of all projects
+        select_exclude : undefined # if given, list of project_id's to exclude from select
+        number_recent : 7     # number of recent projects to include at top if selector is given.
+        cb       : undefined  # cb(err, project_list)
+
+    update_list = (cb) ->
+        if not opts.update and ((store.state.project_list? and not opts.hidden) or (store.state.hidden_project_list? and opts.hidden))
+            # done
+            cb()
+        else
+            salvus_client.get_projects
+                hidden : opts.hidden
+                cb     : (err, mesg) ->
+                    if err
+                        cb(err)
+                    else if mesg.event == 'error'
+                        cb(mesg.error)
+                    else
+                        if opts.hidden
+                            flux.getActions('projects').setTo
+                                hidden_project_list : mesg.projects
+                        else
+                            flux.getActions('projects').setTo
+                                project_list : mesg.projects
+                        cb()
+    update_list (err) ->
+        if err
+            opts.cb?(err)
+        else
+            console.log("NOT IMPLEMENTED")
+
+update_hashtags = (project_list, deleted) ->
+    old_hashtags = undefined
+    if store.state.hashtags?
+        old_hashtags = store.state.hashtags
+    else if localStorage.projects_hashtags?
+        old_hashtags = JSON.parse(localStorage.projects_hashtags)
+    else
+        old_hashtags = {}
+    hashtags = {}
+    for project in project_list
+        if (deleted and project.deleted) or ((not deleted) and (not project.deleted))
+            for k in misc.split((project.title + ' ' + project.description).toLowerCase())
+                if k[0] == "#"
+                    tag = k.slice(1)
+                    if old_hashtags[tag]
+                        hashtags[tag] = true
+                    else
+                        hashtags[tag] = false
+    return hashtags
+
+update_project_list = exports.update_project_list = (cb) ->
+    salvus_client.get_projects
+        hidden : (if store? then store.state.hidden else false)
+        cb: (error, mesg) ->
+            if error or mesg.event != 'all_projects'
+                if not error and mesg?.event == 'error'
+                    error = mesg.error
+                alert_message(type:"error", message:"Unable to update project list (#{error})")
+            hashtags = update_hashtags(mesg.projects, (if store? then store.state.deleted else false))
+            localStorage.projects_hashtags = JSON.stringify(hashtags)
+            if store.state.hidden
+                flux.getActions('projects').setTo
+                    hidden_project_list : mesg.projects
+                    hashtags : hashtags
+                    loading : false
+            else
+                flux.getActions('projects').setTo
+                    project_list : mesg.projects
+                    hashtags : hashtags
+                    loading : false
+            cb?()
+
+exports.open_project = open_project = (opts) ->
+    opts = defaults opts,
+        project   : required
+        item      : undefined
+        target    : undefined
+        switch_to : true
+        cb        : undefined   # cb(err, project)
+
+    project = opts.project
+    if typeof(project) == 'string'
+        # actually a project id
+        x = undefined
+        if store.state.project_list?
+            for p in store.state.project_list
+                if p.project_id == project
+                    x = p
+                    break
+        if not x?
+            # have to get info from database.
+            salvus_client.project_info
+                project_id : project
+                cb         : (err, p) ->
+                    if err
+                        # try again as a public project
+                        salvus_client.public_project_info
+                            project_id : project
+                            cb         : (err, p) ->
+                                if err
+                                    opts.cb?("You do not have access to the project with id '#{project}'")
+                                else
+                                    open_project
+                                        project   : p
+                                        item      : opts.item
+                                        target    : opts.target
+                                        switch_to : opts.switch_to
+                                        cb        : opts.cb
+                    else
+                        open_project
+                            project   : p
+                            item      : opts.item
+                            target    : opts.target
+                            switch_to : opts.switch_to
+                            cb        : opts.cb
+            return
+        else
+            project = x
+
+    proj = project_page(project)
+    top_navbar.resize_open_project_tabs()
+    if opts.switch_to
+        top_navbar.switch_to_page(project.project_id)
+    if opts.target?
+        proj.load_target(opts.target, opts.switch_to)
+
+    opts.cb?(undefined, proj)
+
+create_new_project_dialog = exports.create_new_project_dialog = () ->
+    create_project.modal('show')
+    create_project.find("#projects-create_project-title").focus()
+
+exports.load_target = load_target = (target, switch_to) ->
+    if not target or target.length == 0
+        top_navbar.switch_to_page("projects")
+        return
+    segments = target.split('/')
+    if misc.is_valid_uuid_string(segments[0])
+        t = segments.slice(1).join('/')
+        project_id = segments[0]
+        open_project
+            project   : project_id
+            target    : t
+            switch_to : switch_to
+            cb        : (err) ->
+                if err
+                    alert_message(type:"error", message:err)
+
+ProjectsRefresh = rclass
+    on_click: ->
+        @setState(loading : true)
+        @props.on_click(->setState(loading: false))
+        update_project_list()
+
+    render: ->
+        <Col sm=4>
+

+
+                    <Icon name="refresh" />
+                 Projects
+

+        </Col>
+
+NewProjectButton = rclass
+    render: ->
+        <Col sm=3>
+            <Button bsStyle="primary" style={width: "100%", marginTop: "1ex"} type="submit">
+                <Icon name="plus-circle" /> Create New Project...
+            </Button>
+        </Col>
+
+ProjectsFilterButtons = rclass
+    propTypes:
+        hidden : rtypes.bool.isRequired
+        deleted : rtypes.bool.isRequired
+        hidden_project_list : rtypes.array
+
+    getDefaultProps: ->
+        hidden : false
+        deleted : false
+
+    hiddenClicked: ->
+        if @props.hidden
+            flux.getActions('projects').setTo
+                hidden : false
+                hashtags : update_hashtags(store.state.project_list)
+        else
+            flux.getActions('projects').setTo
+                hidden : true
+                hashtags : (if store.state.hidden_project_list? then update_hashtags(store.state.hidden_project_list) else {})
+        #TODO: improve to not render twice
+        if not @props.hidden_project_list?
+            update_project_list()
+
+    deletedClicked: ->
+        flux.getActions('projects').setTo
+            deleted : not @props.deleted
+            hashtags : update_hashtags(store.state.project_list, not @props.deleted)
+
+    render: ->
+        <Col sm=5>
+            <ButtonGroup style={marginTop: "1ex"} className="pull-right">
+                <Button bsStyle={if @props.deleted then 'warning' else 'info'}
+                        onClick={@deletedClicked}>
+                    <Icon name="trash" /> Deleted
+                </Button>
+                <Button bsStyle={if @props.hidden then 'warning' else 'info'}
+                        onClick={@hiddenClicked}>
+                    <Icon name="eye-slash" /> Hidden
+                </Button>
+            </ButtonGroup>
+        </Col>
+
+ProjectsSearch = rclass
+    propTypes:
+        search : rtypes.string.isRequired
+
+    getDefaultProps: ->
+        search : ""
+
+    delete_search_button: ->
+        <Button><Icon name="times-circle" /></Button>
+
+    search: ->
+        flux.getActions('projects').setTo
+            search : @refs.search.getValue()
+
+    render: ->
+        <Col sm=4>
+            <Input
+                type="search"
+                value = @props.search
+                ref="search"
+                placeholder="Search for projects..."
+                onChange={@search}
+                buttonAfter={@delete_search_button()} />
+        </Col>
+
+ProjectsHashtagGroup = rclass
+    propTypes:
+        hashtags : rtypes.object.isRequired
+
+    getDefaultProps: ->
+        hashtags : {}
+
+    toggleButton: (tag) ->
+        hashtags = @props.hashtags
+        hashtags[tag] = not hashtags[tag]
+        localStorage.projects_hashtags = JSON.stringify(hashtags)
+        flux.getActions('projects').setTo
+            hashtags : hashtags
+
+    render_hashtag: (tag, selected) ->
+        <Button key={tag} onClick={=>@toggleButton(tag)} bsSize="small" bsStyle={if selected then "warning" else "info"}>{"#" + tag}</Button>
+
+    render: ->
+        <Col sm=8>
+            <ButtonGroup>
+                {@render_hashtag(tag, selected) for tag, selected of @props.hashtags}
+            </ButtonGroup>
+        </Col>
+
+ProjectsListingDescription = rclass
+    propTypes:
+        deleted : rtypes.bool.isRequired
+        hidden : rtypes.bool.isRequired
+        hashtags : rtypes.object.isRequired
+        search : rtypes.string.isRequired
+
+    getDefaultProps: ->
+        deleted : false
+        hidden : false
+        hashtags : {}
+        search : ""
+
+    description: ->
+        query = find_text(@props.search, @props.hashtags)
+        desc = "Showing "
+        if @props.deleted
+            desc += "deleted "
+        if @props.hidden
+            desc += "hidden "
+        desc += "projects "
+        if query != ""
+            desc += "whose title, description or users contain '#{query}'."
+        desc
+
+    render: ->
+        <Col sm=12
+             style={color: "#666", marginBottom: "1ex", marginTop: "1ex", fontWeight: "bold", fontSize: "15pt"}
+        >
+        {@description()}
+        </Col>
+
+ProjectRow = rclass
+    propTypes:
+        project       : rtypes.object.isRequired
+
+    render_last_edited: ->
+        try
+            <TimeAgo date={(new Date(@props.project.last_edited)).toISOString()} />
+        catch e
+            console.log("error setting time of project #{@props.project.project_id} to #{@props.project.last_edited} -- #{e}; please report to wstein@gmail.com")
+
+    render_user_list: ->
+        users = []
+        for group in misc.PROJECT_GROUPS
+            if @props.project[group]?
+                for user in @props.project[group]
+                    # this is not working
+                    if user.account_id != salvus_client.account_id
+                        users.push("#{user.first_name} #{user.last_name}")
+        if users.length == 0
+            return ''
+        return '  ' + users.join(', ')
+
+    open_project_from_list: (e) ->
+        open_project
+            project   : @props.project.project_id
+            switch_to : not(e.which == 2 or (e.ctrlKey or e.metaKey))
+            cb        : (err) ->
+                if err
+                    alert_message(type:"error", message:err)
+        return false
+
+    render: ->
+        project_row_styles =
+            backgroundColor : "#ffffff"
+            marginTop       : 0
+            marginBottom    : 0
+            paddingTop      : "1.5em"
+            paddingBottom   : "1.5em"
+            paddingLeft     : "1em"
+            cursor          : "pointer"
+            wordWrap        : "break-word"
+
+        <Well style={project_row_styles} onClick={@open_project_from_list}>
+            <Row>
+                <Col sm=4>
+                    {misc.trunc(html_to_text(@props.project.title), 128)}
+                </Col>
+                <Col sm=2 style={fontSize: "10pt", color: "#666", maxHeight: "7em", overflowY: "auto"}>
+                    {@render_last_edited()}
+                </Col>
+                <Col sm=3 style={marginLeft: 0, color: "#666", maxHeight: "7em", overflowY: "auto"}>
+                    {misc.trunc(html_to_text(@props.project.description),128)}
+                </Col>
+                <Col sm=3 style={marginLeft: 0, maxHeight: "7em", overflowY: "auto"}>
+                    <Icon name='user' style={fontSize: "16pt"}/>
+                    {@render_user_list()}
+                </Col>
+            </Row>
+        </Well>
+
+ShowAllMatchingProjectsButton = rclass
+    propTypes:
+        search : rtypes.bool.isRequired
+
+    show_all_projects: ->
+        flux.getActions('projects').setTo
+            show_all : not @props.show_all
+
+    render: ->
+        <Button onClick={@show_all_projects} bsStyle="info" bsSize="large">Show all matching projects...</Button>
+ProjectList = rclass
+    propTypes:
+        hidden : rtypes.bool
+        deleted : rtypes.bool
+        project_list : rtypes.array
+        hidden_project_list : rtypes.array
+        search : rtypes.string.isRequired
+
+    getDefaultProps: ->
+        hidden : false
+        deleted : false
+        project_list : []
+        hidden_project_list : []
+        search : ""
+
+    search_term: cached_function((project) ->
+        search = (project.title + ' ' + project.description).toLowerCase()
+        for k in misc.split(search)
+            if k[0] == '#'
+                tag = k.slice(1).toLowerCase()
+                search += " [#{k}] "
+        for group in misc.PROJECT_GROUPS
+            if project[group]?
+                for user in project[group]
+                    if user.account_id != salvus_client.account_id
+                        search += (' ' + user.first_name + ' ' + user.last_name + ' ').toLowerCase()
+        return search
+        )
+
+    matches: (project, words) ->
+        search = @search_term(project)
+        if words != []
+            for word in words
+                if word[0] == '#'
+                    word = '[' + word + ']'
+                if search.indexOf(word) == -1
+                    return false
+        return true
+
+    render_row: (project, key) ->
+        <ProjectRow project={project} key={key}/>
+
+    render_list: ->
+        MAX_DEFAULT_PROJECTS = 50
+        query = find_text(@props.search, @props.hashtags)
+        words = misc.split(query)
+        listing = []
+        i = 0
+        v = (if @props.hidden then @props.hidden_project_list else @props.project_list)
+        for project in v
+            if not @props.show_all and i >= MAX_DEFAULT_PROJECTS
+                listing.push <ShowAllMatchingProjectsButton show_all={@props.show_all}/>
+                break
+            if @matches(project, words)
+                i += 1
+                if (@props.deleted and project.deleted) or ((not @props.deleted) and (not project.deleted))
+                    listing.push @render_row(project, i)
+        listing
+
+    render: ->
+        <Col sm=12>
+

+                {@render_list()}
+

+        </Col>
+
+parse_project_tags = (project) ->
+    misc.parse_hashtags((project.title + ' ' + project.description).toLowerCase())
+
+parse_project_search_string = (project) ->
+    search = (project.title + ' ' + project.description).toLowerCase()
+    for k in misc.split(search)
+        if k[0] == '#'
+            tag = k.slice(1).toLowerCase()
+            search += " [#{k}] "
+    for group in misc.PROJECT_GROUPS
+        if project[group]?
+            for user in project[group]
+                if user.account_id != salvus_client.account_id
+                    search += (' ' + user.first_name + ' ' + user.last_name + ' ').toLowerCase()
+    return search
+
+ProjectSelector = rclass
+    getDefaultProps: ->
+        project_list          : undefined    # an array of projects (or undefined = loading...)
+
+        on_project_select     : undefined    # called with project_id and field (e.g., "users"), when a project is clicked on
+        on_refresh            : undefined    # called when user explicitly requests refresh of listing.
+        on_new_project        : undefined    # called when user requests to make a new project
+
+        parse_project_tags          : parse_project_tags    # function that takes project as input and returns its hashtags
+        parse_project_search_string : parse_project_search_string  # function that takes project and strings and returns true on match
+
+    getInitialState: ->
+        @parse_project_search_string = cached_function(@props.parse_project_search_string)
+        state =
+            hidden   : false
+            deleted  : false
+            search   : ''
+            hashtags : {}   # mapping from tag to true/false, where true if selected.
+        return state
+
+    change_filter: (hidden, deleted) ->
+        @setState(hidden:hidden, deleted:deleted)
+
+    change_search: (search) ->
+        @setState(search:search)
+
+    componentWillReceiveProps: ->
+        # clear/update cache
+        for filter, x of @state.hashtags
+            @init_hashtags(filter)
+        @parse_project_search_string.clear_cache()
+
+    project_is_in_filter: (project) ->
+        !!project.hidden == @state.hidden and !!project.deleted == @state.deleted
+
+
+    init_hashtags: (filter) ->
+        # computes the hashtags for the given filter and saves them in state
+        x = {}
+        last = @state.hashtags[filter]
+        for project in @props.project_list
+            if @project_is_in_filter(project)
+                for tag in @props.parse_project_tags(project)
+                    x[tag] = !!(last?[tag])
+        y = misc.copy(@state.hashtags)
+        y[filter] = x
+        @setState(hashtags: y)
+
+    change_hashtag: (tag, selected) ->
+        x = @state.hashtags[@filter()]
+        y = misc.copy(@state.hashtags)
+        y[@filter()][tag] = not x[tag]
+        @setState(hashtags: y)
+
+    filter: -> "#{@state.deleted}-#{@state.hidden}"
+
+    matches: (project, words) ->
+        search = @parse_project_search_string(project)
+        for word in words
+            if word[0] == '#'
+                word = '[' + word + ']'
+            if search.indexOf(word) == -1
+                return false
+        return true
+
+    visible_projects: ->
+        words = misc.split(@state.search).concat(('#'+k for k,selected of @state.hashtags when selected))
+        return (project for project in @props.project_list when @project_is_in_filter(project) and @matches(project, words))
+
+    render: ->
+        if not @props.project_list?
+            # TODO
+            return
Loading...

+        <Grid fluid className="constrained">
+            <Well style={overflow:"hidden"}>
+                <Row>
+                    {if @props.on_refresh? then <ProjectsRefresh on_click={@props.on_refresh} />}
+                    {if @props.new_project? then <NewProjectButton on_create={@props.new_project} />}
+                    <ProjectsFilterButtons hidden={@state.hidden} deleted={@state.deleted} on_change={@change_filter} />
+                </Row>
+                <Row>
+                    <ProjectsSearch search={@state.search} on_change={@change_search} />
+                    <ProjectsHashtagGroup hashtags={@state.hashtags[@filter()]} on_change={@change_hashtag} />
+                </Row>
+                <Row>
+                    <ProjectsListingDescription hidden={@state.hidden} deleted={@state.deleted} search={@state.search} hashtags={@state.hashtags[@filter()]} />
+                </Row>
+                <ProjectList projects={@visible_projects()} />
+            </Well>
+        </Grid>
+
+
+ProjectsPage = rclass
+    on_refresh: update_project_list
+
+    render: ->
+        <FluxComponent flux={flux} connectToStores={'projects'}>
+            <ProjectSelector on_refresh={@on_refresh} />
+        </FluxComponent>
+
+React.render(<ProjectsPage />,  document.getElementById("projects"))
+
+


adding locale_da-dk for angular

adding locale_da-dk for angular

error: pathspec 'src/scripts/angular-locale_da-dk.coffee' did not match any file(s) known to git

--- src/scripts/angular-locale_da-dk.coffee
+++ src/scripts/angular-locale_da-dk.coffee
@@ -0,0 +1,136 @@
+# https://github.com/angular/angular.js/blob/master/src/ngLocale/angular-locale_da-dk.js
+"use strict"
+angular.module "ngLocale", [], [
+  "$provide"
+  ($provide) ->
+    getDecimals = (n) ->
+      n = n + ""
+      i = n.indexOf(".")
+      (if (i is -1) then 0 else n.length - i - 1)
+    getVF = (n, opt_precision) ->
+      v = opt_precision
+      v = Math.min(getDecimals(n), 3)  if `undefined` is v
+      base = Math.pow(10, v)
+      f = ((n * base) | 0) % base
+      v: v
+      f: f
+    getWT = (v, f) ->
+      if f is 0
+        return (
+          w: 0
+          t: 0
+        )
+      while (f % 10) is 0
+        f /= 10
+        v--
+      w: v
+      t: f
+    PLURAL_CATEGORY =
+      ZERO: "zero"
+      ONE: "one"
+      TWO: "two"
+      FEW: "few"
+      MANY: "many"
+      OTHER: "other"
+
+    $provide.value "$locale",
+      DATETIME_FORMATS:
+        AMPMS: [
+          "AM"
+          "PM"
+        ]
+        DAY: [
+          "søndag"
+          "mandag"
+          "tirsdag"
+          "onsdag"
+          "torsdag"
+          "fredag"
+          "lørdag"
+        ]
+        MONTH: [
+          "januar"
+          "februar"
+          "marts"
+          "april"
+          "maj"
+          "juni"
+          "juli"
+          "august"
+          "september"
+          "oktober"
+          "november"
+          "december"
+        ]
+        SHORTDAY: [
+          "søn."
+          "man."
+          "tir."
+          "ons."
+          "tor."
+          "fre."
+          "lør."
+        ]
+        SHORTMONTH: [
+          "jan."
+          "feb."
+          "mar."
+          "apr."
+          "maj"
+          "jun."
+          "jul."
+          "aug."
+          "sep."
+          "okt."
+          "nov."
+          "dec."
+        ]
+        fullDate: "EEEE 'den' d. MMMM y"
+        longDate: "d. MMM y"
+        medium: "dd/MM/y HH.mm.ss"
+        mediumDate: "dd/MM/y"
+        mediumTime: "HH.mm.ss"
+        short: "dd/MM/yy HH.mm"
+        shortDate: "dd/MM/yy"
+        shortTime: "HH.mm"
+
+      NUMBER_FORMATS:
+        CURRENCY_SYM: "kr"
+        DECIMAL_SEP: ","
+        GROUP_SEP: "."
+        PATTERNS: [
+          {
+            gSize: 3
+            lgSize: 3
+            macFrac: 0
+            maxFrac: 3
+            minFrac: 0
+            minInt: 1
+            negPre: "-"
+            negSuf: ""
+            posPre: ""
+            posSuf: ""
+          }
+          {
+            gSize: 3
+            lgSize: 3
+            macFrac: 0
+            maxFrac: 2
+            minFrac: 2
+            minInt: 1
+            negPre: "-"
+            negSuf: " ¤"
+            posPre: ""
+            posSuf: " ¤"
+          }
+        ]
+
+      id: "da-dk"
+      pluralCat: (n, opt_precision) ->
+        i = n | 0
+        vf = getVF(n, opt_precision)
+        wt = getWT(vf.v, vf.f)
+        return PLURAL_CATEGORY.ONE  if n is 1 or wt.t isnt 0 and (i is 0 or i is 1)
+        PLURAL_CATEGORY.OTHER
+
+]


Made spectate mode use top 20 players only

--- server/levels/level_handler.coffee
+++ server/levels/level_handler.coffee
@@ -5,7 +5,7 @@
 Feedback = require('./feedbacks/LevelFeedback')
 Handler = require('../commons/Handler')
 mongoose = require('mongoose')
-
+async = require 'async'
 LevelHandler = class LevelHandler extends Handler
   modelClass: Level
   jsonSchema: require '../../app/schemas/models/level'
@@ -220,7 +220,7 @@
         userMap[u._id] = u[serviceProperty] for u in userResults
         session[serviceProperty] = userMap[session.creator] for session in sessionResults
         res.send(sessionResults)
-
+
   getRandomSessionPair: (req, res, slugOrID) ->
     findParameters = {}
     if Handler.isID slugOrID
@@ -235,32 +235,34 @@
     query.exec (err, level) =>
       return @sendDatabaseError(res, err) if err
       return @sendNotFoundError(res) unless level?
-
+
       sessionsQueryParameters =
         level:
           original: level.original.toString()
           majorVersion: level.version.major
         submitted:true
-
-      query = Session
-        .find(sessionsQueryParameters)
-        .select('team')
-        .lean()
-
-      query.exec (err, resultSessions) =>
-        return @sendDatabaseError res, err if err? or not resultSessions
-
-        teamSessions = _.groupBy resultSessions, 'team'
-        sessions = []
-        numberOfTeams = 0
-        for team of teamSessions
-          numberOfTeams += 1
-          sessions.push _.sample(teamSessions[team])
-        if numberOfTeams != 2 then return @sendDatabaseError res, "There aren't sessions of 2 teams, so cannot choose random opponents!"
-
-        @sendSuccess res, sessions
-
-
+
+      query = Session.find(sessionsQueryParameters).distinct("team")
+      query.exec (err, teams) =>
+        return @sendDatabaseError res, err if err? or not teams
+        findTop20Players = (sessionQueryParams, team, cb) ->
+          sessionQueryParams["team"] = team
+          Session.aggregate [
+            {$match: sessionQueryParams}
+            {$project: {"totalScore":1}}
+            {$sort: {"totalScore":-1}}
+            {$limit: 20}
+          ], cb
+
+        async.map teams, findTop20Players.bind(@, sessionsQueryParameters), (err, map) =>
+          if err? then return @sendDatabaseError(res, err)
+          sessions = []
+          for mapItem in map
+            sessions.push _.sample(mapItem)
+          if map.length != 2 then return @sendDatabaseError res, "There aren't sessions of 2 teams, so cannot choose random opponents!"
+          @sendSuccess res, sessions
+
+
   getFeedback: (req, res, id) ->
     return @sendNotFoundError(res) unless req.user
     @fetchLevelByIDAndHandleErrors id, req, res, (err, level) =>


implementing new groups filtering

implementing new groups filtering

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/leonidas/qa-dashboard.git/'


Added forgotten file...

Added forgotten file...

error: pathspec 'core/app/backbone/factlink/start_history.coffee' did not match any file(s) known to git

--- core/app/backbone/factlink/start_history.coffee
+++ core/app/backbone/factlink/start_history.coffee
@@ -0,0 +1,5 @@
+Backbone.Factlink ||= {}
+
+Backbone.Factlink.startHistory = ->
+  $ ->
+    Backbone.history.start pushState:Modernizr.history


Save all extra data [DULUX-40]

Save all extra data [DULUX-40]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Bogdan-p/bookingbug-angular.git/'


Increment line row by 1 in label

Increment line row by 1 in label

--- src/extensions/outline-view/outline-view.coffee
+++ src/extensions/outline-view/outline-view.coffee
@@ -25,7 +25,7 @@
       @li =>
         @div name, class: 'function-name'
         @div class: 'right', =>
-          @div "Line #{row}", class: 'function-line'
+          @div "Line #{row + 1}", class: 'function-line'
         @div class: 'clear-float'

   toggle: ->


Mainview: dock items select/deselect logic fixed


- Fix registrationForm security breaches


landing: return a default value for getPayment util

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

--- client/landing/site.landing/coffee/core/utils.coffee
+++ client/landing/site.landing/coffee/core/utils.coffee
@@ -49,7 +49,7 @@
   eraseCardInfo()
   delete global._payment

-getPayment = -> global._payment
+getPayment = -> global._payment ? {}

 module.exports = utils = {


This change gives custom repositoryProviders more priority - this wil allow us to override base git repository implementation

--- src/project.coffee
+++ src/project.coffee
@@ -288,7 +288,7 @@
       'atom.repository-provider',
       '^0.1.0',
       (provider) =>
-        @repositoryProviders.push(provider)
+        @repositoryProviders.unshift(provider)
         @setPaths(@getPaths()) if null in @repositories
         new Disposable =>
           @repositoryProviders.splice(@repositoryProviders.indexOf(provider), 1)


cache: use 'or' operator

cache: use 'or' operator

--- workers/social/lib/social/cache/main.coffee
+++ workers/social/lib/social/cache/main.coffee
@@ -2,7 +2,7 @@
 cachingTimeInMS = 30000

 repeatFetchingItems = (cacheKey, fetcherFn, fetcherFnOptions)->
-  inProgress = cache[cacheKey]?.inProgress || no
+  inProgress = cache[cacheKey]?.inProgress or no

   return  if inProgress

@@ -29,7 +29,7 @@
       {data, ttl} = cache[cacheKey]
       callback null, data

-      if (Date.now() - (ttl || 0)  > cachingTimeInMS)
+      if (Date.now() - (ttl or 0)  > cachingTimeInMS)
         repeatFetchingItems cacheKey, fetcherFn, fetcherFnOptions
     else
       repeatFetchingItems cacheKey, fetcherFn, fetcherFnOptions


JNewApp: Add publish method which creates the app if not exists and updates if its


Reset tweet count to 0 before counting again

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Arm1stice/prosu.git/'


fix geo queries

fix geo queries

--- controllers/generic/controller.find.coffee
+++ controllers/generic/controller.find.coffee
@@ -39,7 +39,7 @@
       #Remove undefined params
       #(as well as limit, skip, and sort)
       where = _.transform params, (result, param, key)->
-        if key not in ['limit', 'offset', 'skip', 'sort'] and param
+        if key not in ['limit', 'offset', 'skip', 'sort'] and not context.options.queries[key] and param
           if _.isString param
             param = tryToParseJSON param


Add test for validation of document input

error: pathspec 'test/document_test.coffee' did not match any file(s) known to git

--- test/document_test.coffee
+++ test/document_test.coffee
@@ -0,0 +1,46 @@
+treeSitter = require "tree-sitter"
+assert = require "assert"
+compiler = require ".."
+
+describe "Document", ->
+  document = null
+  parser = null
+
+  before ->
+    grammar = compiler.grammar
+      name: "test"
+      rules:
+        stuff: -> "stuff"
+
+    parser = compiler.compileAndLoad(grammar)
+
+  beforeEach ->
+    document = new treeSitter.Document()
+    document.setParser(parser)
+
+  describe "setParser", ->
+    describe "when the supplied object is not a parser", ->
+      it "throws an exception", ->
+        assert.throws((->
+          document.setParser({})
+        ), /Invalid parser/)
+
+  describe "setInput", ->
+    describe "when the supplied object does not implement .seek(n)", ->
+      it "throws an exception", ->
+        assert.throws((->
+          document.setInput({
+            seek: (n) -> 0
+          })
+        ), /Input.*implement.*read/)
+
+        assert.throws((->
+          document.setInput({
+            read: -> ""
+          })
+        ), /Input.*implement.*seek/)
+
+        document.setInput({
+          read: -> ""
+          seek: (n) -> 0
+        })


Lower case Task in require

Lower case Task in require

--- src/packages/snippets/src/snippets-task.coffee
+++ src/packages/snippets/src/snippets-task.coffee
@@ -1,4 +1,4 @@
-Task = require 'Task'
+Task = require 'task'
 TextMatePackage = require 'text-mate-package'

 module.exports =


server: implement unregister handler

server: implement unregister handler

error: pathspec 'servers/lib/server/handlers/unregister.coffee' did not match any file(s) known to git

--- servers/lib/server/handlers/unregister.coffee
+++ servers/lib/server/handlers/unregister.coffee
@@ -0,0 +1,15 @@
+bongo                 = require './../bongo'
+{ generateFakeClient } = require './../client'
+module.exports = (req, res) ->
+
+  generateFakeClient req, res, (err, client, session) ->
+    return res.status(500).send err  if err
+
+    { nickname } = client?.connection?.delegate?.profile
+    return res.status(500).send "nickname is not set"  unless nickname
+
+    { JUser } = bongo.models
+    JUser.unregister client, nickname, (err) ->
+      return res.status(500).send err  if err
+
+      return res.status(200).end()


Add spec for checking webgl support.

Add spec for checking webgl support.

--- spec/chromium-spec.coffee
+++ spec/chromium-spec.coffee
@@ -65,3 +65,8 @@
     it 'does not crash', ->
       RUint8Array = require('remote').getGlobal 'Uint8Array'
       new RUint8Array
+
+  describe 'webgl', ->
+    it 'can be get as context in canvas', ->
+      webgl = document.createElement('canvas').getContext 'webgl'
+      assert.notEqual webgl, null


Order controller added

Order controller added

error: pathspec 'src/controllers/order.coffee' did not match any file(s) known to git

--- src/controllers/order.coffee
+++ src/controllers/order.coffee
@@ -0,0 +1,67 @@
+app = require process.cwd() + '/app'
+db  = app.get 'models'
+
+# Order model's CRUD controller.
+module.exports =
+
+  # Lists all orders
+  index: (req, res) ->
+    db.Order.findAll()
+      .success (result) ->
+        res.format
+          json: -> res.json result
+          html: -> res.render 'orders', orders: result
+
+  # Creates new order with data from `req.body`
+  create: (req, res) ->
+    db.Order.create req.body
+      .success (result) ->
+        if result.ask is 0 then result.ask
+        else delete result.bid
+        res.statusCode = 201
+        res.send result
+      .error (err) ->
+        res.statusCode = 501
+        res.send err
+
+  # Gets order by id
+  get: (req, res) ->
+    db.Order.find req.params.id
+      .success (result) ->
+        if not result?
+          res.statusCode = 404
+          res.render '404', 404
+        else
+          res.send result
+      .error (err) ->
+        res.statusCode = 500
+        res.send err
+
+  # Updates order with data from `req.body`
+  update: (req, res) ->
+    db.Order.update req.body,
+        id: req.params.id
+      .complete (err, result) ->
+        if not err?
+          res.statusCode = 204
+          res.end()
+        else
+          res.statusCode = 500
+          res.send err
+
+  # Deletes order by id
+  delete: (req, res) ->
+    db.Order.find
+        where:
+          id: req.params.id
+      .success (result) ->
+        if not result?
+          res.statusCode = 404
+          res.render '404', 404
+        else
+          result.destroy().success ->
+            res.statusCode = 204
+            res.end()
+      .error (err) ->
+        res.statusCode = 500
+        res.send err


Added log setting for production.

Added log setting for production.

--- server_setup.coffee
+++ server_setup.coffee
@@ -8,7 +8,6 @@
 baseRoute = require './server/routes/base'
 user = require './server/users/user_handler'
 logging = require './server/commons/logging'
-
 config = require './server_config'

 ###Middleware setup functions implementation###
@@ -20,9 +19,16 @@
       self.emit('pass',message)
     next()

+productionLogging = (tokens, req, res)->
+  status = res.statusCode
+  color = 31
+  if(status != 200 && status != 304)
+    return '\x1b[90m' + req.method+ ' ' + req.originalUrl + ' '+ '\x1b[' + color + 'm' + res.statusCode+ ' \x1b[90m'+ (new Date - req._startTime)+ 'ms' + '\x1b[0m';
+
 setupExpressMiddleware = (app) ->
   setupRequestTimeoutMiddleware app
-  app.use(express.logger('dev'))
+  express.logger.format('prod', productionLogging)
+  app.use(express.logger('prod'))
   app.use(express.static(path.join(__dirname, 'public')))
   app.use(useragent.express())


Shift everythingone pixel to fix the build

--- spec/javascripts/backbone/views/tracker_view_spec.js.coffee
+++ spec/javascripts/backbone/views/tracker_view_spec.js.coffee
@@ -20,22 +20,22 @@
       expect($(".bar-chart g.iteration-state-counts-chart g.x.axis")).toExist()
       expect($(".bar-chart g.iteration-state-counts-chart g.y.axis")).toExist()

-      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(0).attr('x')).toContain("39")
+      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(0).attr('x')).toContain("40")
       expect($(".bar-chart g.iteration-state-counts-chart rect").eq(0).attr('y')).toContain("109")

-      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(1).attr('x')).toContain("114")
+      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(1).attr('x')).toContain("115")
       expect($(".bar-chart g.iteration-state-counts-chart rect").eq(1).attr('y')).toContain("73")

-      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(2).attr('x')).toContain("189")
+      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(2).attr('x')).toContain("190")
       expect($(".bar-chart g.iteration-state-counts-chart rect").eq(2).attr('y')).toContain("118")

-      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(3).attr('x')).toContain("264")
+      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(3).attr('x')).toContain("265")
       expect($(".bar-chart g.iteration-state-counts-chart rect").eq(3).attr('y')).toContain("73")

-      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(4).attr('x')).toContain("339")
+      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(4).attr('x')).toContain("340")
       expect($(".bar-chart g.iteration-state-counts-chart rect").eq(4).attr('y')).toContain("10")

-      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(5).attr('x')).toContain("414")
+      expect($(".bar-chart g.iteration-state-counts-chart rect").eq(5).attr('x')).toContain("415")
       expect($(".bar-chart g.iteration-state-counts-chart rect").eq(5).attr('y')).toContain("109")

     describe "when the tracker model is offline", ->


init menus/

init menus/

error: pathspec 'menus/bower-install.cson' did not match any file(s) known to git

--- menus/bower-install.cson
+++ menus/bower-install.cson
@@ -0,0 +1,13 @@
+# See https://atom.io/docs/latest/creating-a-package#menus for more details
+'menu': [
+  {
+    'label': 'Packages'
+    'submenu': [
+      'label': 'bower install'
+      'submenu': [
+        { 'label': '--save', 'command': 'bower-install:save' }
+        { 'label': '--save-dev', 'command': 'bower-install:save-dev' }
+      ]
+    ]
+  }
+]


update to widget.directive to support new widget.metadata.template architecture

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/xaun/impac-angular.git/'


Only read actual package.json files from disk in compile-packages-slug task

--- build/tasks/compile-packages-slug-task.coffee
+++ build/tasks/compile-packages-slug-task.coffee
@@ -40,6 +40,8 @@
       continue if path.basename(moduleDirectory) is '.bin'

       metadataPath = path.join(moduleDirectory, 'package.json')
+      continue unless fs.existsSync(metadataPath)
+
       metadata = grunt.file.readJSON(metadataPath)
       continue unless metadata?.engines?.atom?


Fixed issue with user calendar colors

Fixed issue with user calendar colors

Closes #18505

--- app/assets/javascripts/users/calendar.js.coffee
+++ app/assets/javascripts/users/calendar.js.coffee
@@ -6,12 +6,6 @@
     @daySizeWithSpace = @daySize + (@daySpace * 2)
     @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
     @months = []
-    @highestValue = 0
-
-    # Get the highest value from the timestampes
-    _.each timestamps, (count) =>
-      if count > @highestValue
-        @highestValue = count

     # Loop through the timestamps to create a group of objects
     # The group of objects will be grouped based on the day of the week they are
@@ -39,8 +33,8 @@
       i++

     # Init color functions
+    @colorKey = @initColorKey()
     @color = @initColor()
-    @colorKey = @initColorKey()

     # Init the svg element
     @renderSvg(group)
@@ -104,7 +98,7 @@
       .attr 'class', 'user-contrib-cell js-tooltip'
       .attr 'fill', (stamp) =>
         if stamp.count isnt 0
-          @color(stamp.count)
+          @color(Math.min(stamp.count, 40))
         else
           '#ededed'
       .attr 'data-container', 'body'
@@ -164,10 +158,11 @@
         color

   initColor: ->
+    colorRange = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
     d3.scale
-      .linear()
-      .range(['#acd5f2', '#254e77'])
-      .domain([0, @highestValue])
+      .threshold()
+      .domain([0, 10, 20, 30])
+      .range(colorRange)

   initColorKey: ->
     d3.scale


Fix not yet ready bookyt/table_select JS inclusion.

--- app/assets/javascripts/application.js.coffee
+++ app/assets/javascripts/application.js.coffee
@@ -13,5 +13,4 @@
 #= require accounting
 #= require accounting-jquery
 #= require bootstrap-datepicker
-#= require bookyt/table_select
 #= require_tree .


Scroll to comment hotfix

Scroll to comment hotfix

--- app/assets/javascripts/discussions.js.coffee
+++ app/assets/javascripts/discussions.js.coffee
@@ -8,7 +8,7 @@
 $ ->
   if $("body.discussions.show").length > 0

-    if $('#js-dog-ear').length > 0
+    if $('#js-dog-ear').length > 0 && !window.location.hash
       $('html,body').animate
         scrollTop: $('#js-dog-ear').offset().top - 75


Call mouse leave function if info box is open.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


Remove metadata

Remove metadata

--- plugins/pagerduty/index.coffee
+++ plugins/pagerduty/index.coffee
@@ -2,16 +2,15 @@

 class PagerDuty extends NotificationPlugin
   stacktraceLines = (stacktrace) ->
-    ("#{line.file}:#{line.lineNumber} - #{line.method}" for line in stacktrace when line.inProject)
-
+    ("#{line.file}:#{line.lineNumber} - #{line.method}" for line in stacktrace when line.inProject)
+
   pagerDutyDetails = (event) ->
-    details =
+    details =
       message : event.trigger.message
       project : event.project.name
       class : event.error.exceptionClass
       url : event.error.url
       stackTrace : event.error.stacktrace
-      metaData : event.error.metaData
     details

   @receiveEvent: (config, event, callback) ->


added load event handler to KDView so we can use it for image tooltip size detection later on

--- client/Framework/core/KDView.coffee
+++ client/Framework/core/KDView.coffee
@@ -20,7 +20,8 @@
     contextmenu|
     scroll|
     paste|
-    error
+    error|
+    load
     )$
     ///

@@ -503,6 +504,8 @@

   scroll:(event)->     yes

+  load:(event)->       yes
+
   error:(event)->      yes

   keyUp:(event)->      yes


Add menu bar

Add menu bar

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Hiroto-K/EncryptionHelper.git/'


Added item model.

Added item model.

error: pathspec 'app/assets/javascripts/app/models/item.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/app/models/item.js.coffee
+++ app/assets/javascripts/app/models/item.js.coffee
@@ -0,0 +1,5 @@
+attr = DS.attr;
+
+App.Item = DS.Model.extend {
+  name: attr('string')
+}


Refactor coffee code for make it nice looking

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/microweb10/urlmini.git/'


Base64 encode and decode strings

Base64 encode and decode strings

error: pathspec 'src/scripts/base64.coffee' did not match any file(s) known to git

--- src/scripts/base64.coffee
+++ src/scripts/base64.coffee
@@ -0,0 +1,10 @@
+# Base64 encoding and decoding.
+#
+# base64 encode|decode <query> - Base64 encode or decode <string>
+
+module.exports = (robot) ->
+  robot.respond /base64 encode( me)? (.*)/i, (msg) ->
+    msg.send new Buffer(msg.match[2]).toString('base64')
+
+  robot.respond /base64 decode( me)? (.*)/i, (msg) ->
+    msg.send new Buffer(msg.match[2], 'base64').toString('utf8')


Add remove filter button

Add remove filter button

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/hlecuanda/conda-ui.git/'


Finished core functionality of TW class, added jQuery / Zepto function

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/paulspringett/tw-share.git/'


 Merge branch 'master.addOptionsToAssurerInJraphical' into 'master'

Master.Add Options To Assurer In Jraphical

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Add max validator spec

Add max validator spec

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lonelyplanet/rizzo.git/'


fix: fix app init when missing attributes

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/keboola/kbc-ui-ex-salesforce.git/'


Fixed the archive clip download error. (#2118)

* Fixed the archive clip download error.

* Set the src url for archive clip on archive dailogue.


update CM-Engine blog path

update CM-Engine blog path

 On branch master

	modified:   app.coffee

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/FireworksProject/corkboard-website.git/'


adapt onClickBar

adapt onClickBar


reverted changes

reverted changes

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/review.git/'


Server: implement csrf protection

Server: implement csrf protection


Whoops fixed color modifier, bugfix to changing colors when on a lower part of file

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jrattray13/swackets.git/'


implemented insert and append

implemented insert and append

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ChHeLeJa/SpaceTrader.git/'


Renamed to TaskRunner.

Renamed to TaskRunner.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/urbanetic/bismuth-schema.git/'


Skipped inserting entities if errors occurred when determining geometry.


Added logic to set specific parameters if the asset is an IFC file.


Let's be nice

Let's be nice

--- bot.coffee
+++ bot.coffee
@@ -55,3 +55,4 @@
     move = randomMove()
   console.log JSON.stringify
     move: move
+  process.exit 0


Initial bot code

Initial bot code

error: pathspec 'bot.coffee' did not match any file(s) known to git

--- bot.coffee
+++ bot.coffee
@@ -0,0 +1,28 @@
+fs = require "fs"
+Steam = require "steam"
+
+DogeTipDiscussions = "http://steamcommunity.com/groups/DogeTip/discussions"
+DogeTipGroupID = "103582791435182182"
+
+bot = new Steam.SteamClient()
+{credentials} = require "./auth.coffee"
+bot.logOn credentials
+
+
+
+bot.on "loggedOn", ->
+	console.log "Logged in as '#{credentials.accountName}'"
+	bot.setPersonaState Steam.EPersonaState.Online # to display your bot's status as "Online"
+	console.log "SteamID: " + bot.steamID
+
+	bot.joinChat DogeTipGroupID
+	bot.sendMessage DogeTipGroupID, "dogetippingbot is back online"
+
+bot.on "chatMsg", (sourceID, message, type, chatterID) ->
+	console.log "Received chat message: " + message
+	if message == "Friend"
+		bot.addFriend chatterID
+	#bot.sendMessage sourceID, "Your steamID is: " + chatterID #, Steam.EChatEntryType.ChatMsg); // ChatMsg by default
+bot.on "friend", (steamID, Relationship) ->
+	console.log "steamID: #{steamID}"
+	console.log "Relationship: #{Relationship}"


Remove kudosu tab

Remove kudosu tab

--- resources/assets/coffee/react/ranking/page.coffee
+++ resources/assets/coffee/react/ranking/page.coffee
@@ -34,9 +34,6 @@
         disabled: true
       country:
         title: osu.trans('ranking.type.country')
-        disabled: true
-      kudosu:
-        title: osu.trans('ranking.type.kudosu')
         disabled: true

     @state =


adds $scope.$apply to watchPosition test (the method returns a stream)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/supersonic.git/'


landing/billing: add error view for generic errors

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

--- client/landing/site.landing/coffee/team/forms/stripepaymenttabform.coffee
+++ client/landing/site.landing/coffee/team/forms/stripepaymenttabform.coffee
@@ -45,6 +45,7 @@

     @backLink = @getButtonLink 'BACK', '/Team/Domain'
     @resetFormLink = @getResetFormLink()
+    @errorView = @getErrorView()

     @on [ 'FormSubmitFailed', 'FormValidationFailed' ], @button.bound 'hideLoader'

@@ -59,6 +60,21 @@

     @forEachInputView (input) -> input.hide()
     @resetFormLink.show()
+
+
+  showFatalError: ({ message, nextStep }) ->
+
+    @showReset()
+    @errorView.show()
+
+    @errorView.destroySubViews()
+    @errorView.addSubView new kd.CustomHTMLView
+      tagName: 'h4'
+      partial: message
+
+    @errorView.addSubView new kd.CustomHTMLView
+      tagName: 'h5'
+      partial: nextStep

   forEachInputView: (callback) ->
@@ -188,9 +204,16 @@
       click    : callback

+  getErrorView: ->
+
+    new kd.CustomHTMLView
+      cssClass: 'hidden cc-form-errorView'
+
+
   pistachio: ->

     """
+    {{> @errorView }}
     <div class='cc-form-resetLink'>
       {{> @resetFormLink}}
     </div>


Test a mix of CRUD calls

Test a mix of CRUD calls

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/fuzzy-ai/microservice-client.git/'


api weibo

api weibo

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/YY030913/tp.git/'


Modal closes if clicked somewhere outside it

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/RobertsGroza/kakimasu.git/'


Updated menu styles to match new class names


client/notif: emit special events for machine share

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

--- client/app/lib/notificationcontroller.coffee
+++ client/app/lib/notificationcontroller.coffee
@@ -128,10 +128,16 @@
             storage.machines.pop machine
             reactor.dispatch actions.INVITATION_REJECTED, machine._id

+          @emit 'MachineShare:Removed', { machine }
+
         when 'added'
           storage.machines.fetch 'uid', machineUId
             .then (machine) ->
               reactor.dispatch actions.LOAD_USER_ENVIRONMENT_SUCCESS, [ machine ]
+              return machine
+
+            .then (machine) =>
+              @emit 'MachineShare:Added', { machine }
               return machine

             .catch (err) ->