update and shutdown commands

update and shutdown commands

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/'


bug fix

bug fix


Note code dup in CocoModel.updateI18nCoverage

--- app/models/CocoModel.coffee
+++ app/models/CocoModel.coffee
@@ -429,6 +429,8 @@
     pathToData = {}
     attributes ?= @attributes

+    # TODO: Share this code between server and client
+    # NOTE: If you edit this, edit the server side version as well!
     TreemaUtils.walk(attributes, @schema(), null, (path, data, workingSchema) ->
       # Store parent data for the next block...
       if data?.i18n


added missing script file

added missing script file

git-svn-id: 00f01ee4f729ccc52c3e336777c3e81b5adc88db@103128 ef392f78-ee14-0410-84e5-9db46baae5bb

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

--- app/scripts/newsdesk.coffee
+++ app/scripts/newsdesk.coffee
@@ -0,0 +1,96 @@
+# SB-newsdesk 1.0b
+# Requirements: JQuery, JQuery.ui.position, trust filter, loc filter, Font Awesome
+
+angular.module('newsdesk', []).directive "newsDesk", ($window, $document, $rootElement, $http, $location) ->
+    template : '''
+

+

+
+

+                {{numNewNews}}
+

+

+

+

+
{{header | loc}}×

+

+
 lastChecked)}">
+
{{item.t[currentLang]}}

+                    {{item.d}}
+

+

+

+

+

+    '''
+    restrict : "EA"
+    replace : true
+    scope : { "header" : "=", "storage" : "=" }
+    link : (scope, elem, attr) ->
+        s = scope
+        s.shouldUseThis = () ->
+            return settings.news_desk_url?
+
+        if s.shouldUseThis()
+            s.newsitems = []
+            s.initData = () ->
+                s.lastChecked = localStorage.getItem(s.storage) or "0000-00-00"
+                $.ajax({
+                    type: "GET",
+                    url: settings.news_desk_url,
+                    async: false,
+                    jsonpCallback: "newsdata",
+                    contentType: "application/json",
+                    dataType: "jsonp",
+                    success: (json) ->
+                        currentDate = new Date().toISOString()[0..9]
+                        s.newsitems = (newsitem for newsitem in json when ((not newsitem.e?) or (newsitem.e >= currentDate)))
+                        n = 0
+                        for n_item in s.newsitems
+                            if n_item.d > s.lastChecked
+                                n += 1
+                        s.$apply(() -> s.numNewNews = n)
+                    error: (e) ->
+                       console.log "error, couldn't get news", e.message
+                });
+
+            s.currentLang = $location.search().lang or "sv"
+
+            s.numNewNews = 0
+            s.initData()
+
+            s.togglePopover = (event) ->
+                if s.isPopoverVisible
+                    s.popHide()
+                else
+                    s.currentLang = $location.search().lang or "sv"
+                    s.popShow()
+                    s.numNewNews = 0
+                event.preventDefault()
+                event.stopPropagation()
+
+            popover = $(".newsdesk-popover")
+            s.isPopoverVisible = false
+
+            handleEscape = (event) ->
+                if event.which is 27
+                    s.popHide()
+                    return false
+
+            s.popShow = () ->
+                s.isPopoverVisible = true
+
+                popover.show().focus().position
+                    my : "right top"
+                    at : "right-10 top+10"
+                    of : window
+                $rootElement.on "keydown", handleEscape
+                $rootElement.on "click", s.popHide
+
+                localStorage.setItem s.storage, s.newsitems[0].d
+
+            s.popHide = () ->
+                s.isPopoverVisible = false
+                popover.hide()
+                $rootElement.off "keydown", handleEscape
+                $rootElement.off "click", s.popHide


fix test

fix test

--- test/lib/MeshbluWebsocketHandler-spec.coffee
+++ test/lib/MeshbluWebsocketHandler-spec.coffee
@@ -181,7 +181,7 @@
         expect(@sut.sendFrame).to.have.been.calledWith 'ready', uuid: '1234', token: 'abcd', status: 200

       it 'should emit subscribe to my uuid received and broadcast', ->
-        expect(@messageIOClient.subscribe).to.have.been.calledWith '1234', ['received', 'broadcast']
+        expect(@messageIOClient.subscribe).to.have.been.calledWith '1234', ['received']

   describe 'status', ->
     beforeEach ->


minor bugfix

minor bugfix

--- client/Social/Activity/views/messagepane.coffee
+++ client/Social/Activity/views/messagepane.coffee
@@ -9,7 +9,7 @@

     {itemClass, type} = @getOptions()

-    @createParticipantsView()
+    @createParticipantsView() if @getData().typeConstant is 'privatemessage'
     @listController = new ActivityListController {itemClass}
     @createInputWidget()

@@ -81,7 +81,7 @@

   viewAppended: ->

-    @addSubView @participantsView
+    @addSubView @participantsView if @participantsView
     @addSubView @input  if @input
     @addSubView @listController.getView()
     @populate()


Kites: Add manifest into kite data.

Kites: Add manifest into kite data.

--- client/Social/Apps/Views/createkitemodal.coffee
+++ client/Social/Apps/Views/createkitemodal.coffee
@@ -9,7 +9,7 @@
     options.width             = 760
     options.height            = "auto"
     options.tabs              =
-      # navigable               : no
+      navigable               : no
       forms                   :
         Details               :
           buttons             :
@@ -79,10 +79,15 @@
     @pricingForms.push pricingForm

   save: ->
-    details = @modalTabs.forms.Details.getFormData()
-    plans   = (form.getFormData() for form in @pricingForms)
+    {name, description} = @modalTabs.forms.Details.getFormData()
+    plans               = (form.getFormData() for form in @pricingForms)
+    kite                =
+      name              : name
+      manifest          :
+        description     : description
+        name            : name

-    KD.remote.api.JKite.create details, (err, kite)=>
+    KD.remote.api.JKite.create kite, (err, kite)=>
       return  KD.showError err if err
       {dash} = Bongo
       queue = plans.map (plan) -> ->


teams: admin: stacks: show credential modal code highlighting

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/'


Remove restrictive zip validation

Remove restrictive zip validation

--- components/credit_card/client/error_handling_form.coffee
+++ components/credit_card/client/error_handling_form.coffee
@@ -22,7 +22,7 @@
   isEmail: ($el) -> isEmail $el.val()
   isPresent: ($el) -> $el.val()? && $.trim($el.val()).length > 0
   isState: ($el) => @isPresent($el) || $el.parent().parent().find('select.country').val() != 'USA'
-  isZip: ($el) => @isPresent($el) && ($el.parent().parent().find('select.country').val() != 'USA' || $el.val().trim().match(/^\d{5}/))
+  isZip: ($el) => @isPresent($el)

   clearErrors: ->
     @$el.find('.has-error').removeClass('has-error')


Add HTTP route handler scope tests.

Add HTTP route handler scope tests.

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/RobotSnacks/stout-server.git/'


add ability to get and remove global Palettes by index

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/aligerum/umbriel.git/'


Use actual property for overlayer

Use actual property for overlayer

--- src/react-editor-view.coffee
+++ src/react-editor-view.coffee
@@ -20,8 +20,6 @@
   Object.defineProperty @::, 'charWidth', get: -> @editor.getDefaultCharWidth()
   Object.defineProperty @::, 'firstRenderedScreenRow', get: -> @component.getRenderedRowRange()[0]
   Object.defineProperty @::, 'lastRenderedScreenRow', get: -> @component.getRenderedRowRange()[1]
-  Object.defineProperty @::, 'overlayer', get: -> this
-
   append: (view) ->
     @appendToLinesView(view)

@@ -52,6 +50,7 @@
     node = @component.getDOMNode()

     @underlayer = $(node).find('.selections')
+    @overlayer = $(node).find('.lines')

     @gutter = $(node).find('.gutter')
     @gutter.removeClassFromAllLines = (klass) =>


Hacks on hacks on hacks to test on test on test

--- build/tasks/publish-build-task.coffee
+++ build/tasks/publish-build-task.coffee
@@ -37,8 +37,8 @@
         isPrerelease = false
       when 'beta'
         isPrerelease = true
-      else
-        return
+      # else
+      #   return

     doneCallback = @async()
     startTime = Date.now()
@@ -55,12 +55,16 @@

     zipAssets buildDir, assets, (error) ->
       return done(error) if error?
-      getAtomDraftRelease isPrerelease, channel, (error, release) ->
-        return done(error) if error?
-        assetNames = (asset.assetName for asset in assets)
-        deleteExistingAssets release, assetNames, (error) ->
-          return done(error) if error?
-          uploadAssets(release, buildDir, assets, done)
+      uploadAssets(null, buildDir, assets, done)
+
+    # zipAssets buildDir, assets, (error) ->
+    #   return done(error) if error?
+    #   getAtomDraftRelease isPrerelease, channel, (error, release) ->
+    #     return done(error) if error?
+    #     assetNames = (asset.assetName for asset in assets)
+    #     deleteExistingAssets release, assetNames, (error) ->
+    #       return done(error) if error?
+    #       uploadAssets(release, buildDir, assets, done)

 getAssets = ->
   {cp} = require('./task-helpers')(grunt)
@@ -258,6 +262,6 @@
   tasks = []
   for {assetName} in assets
     assetPath = path.join(buildDir, assetName)
-    tasks.push(uploadToReleases.bind(this, release, assetName, assetPath))
+    # tasks.push(uploadToReleases.bind(this, release, assetName, assetPath))
     tasks.push(uploadToS3.bind(this, release, assetName, assetPath))
   async.parallel(tasks, callback)


Revert "Hacks on hacks on hacks to test on test on test"

This reverts commit 220b0e67e63b43145f42b1620591469503ae8341.

--- build/tasks/publish-build-task.coffee
+++ build/tasks/publish-build-task.coffee
@@ -37,8 +37,8 @@
         isPrerelease = false
       when 'beta'
         isPrerelease = true
-      # else
-      #   return
+      else
+        return

     doneCallback = @async()
     startTime = Date.now()
@@ -55,16 +55,12 @@

     zipAssets buildDir, assets, (error) ->
       return done(error) if error?
-      uploadAssets({tag_name: '1.1'}, buildDir, assets, done)
-
-    # zipAssets buildDir, assets, (error) ->
-    #   return done(error) if error?
-    #   getAtomDraftRelease isPrerelease, channel, (error, release) ->
-    #     return done(error) if error?
-    #     assetNames = (asset.assetName for asset in assets)
-    #     deleteExistingAssets release, assetNames, (error) ->
-    #       return done(error) if error?
-    #       uploadAssets(release, buildDir, assets, done)
+      getAtomDraftRelease isPrerelease, channel, (error, release) ->
+        return done(error) if error?
+        assetNames = (asset.assetName for asset in assets)
+        deleteExistingAssets release, assetNames, (error) ->
+          return done(error) if error?
+          uploadAssets(release, buildDir, assets, done)

 getAssets = ->
   {cp} = require('./task-helpers')(grunt)
@@ -263,6 +259,6 @@
   tasks = []
   for {assetName} in assets
     assetPath = path.join(buildDir, assetName)
-    # tasks.push(uploadToReleases.bind(this, release, assetName, assetPath))
+    tasks.push(uploadToReleases.bind(this, release, assetName, assetPath))
     tasks.push(uploadToS3.bind(this, release, assetName, assetPath))
   async.parallel(tasks, callback)


Add short delay to setting #classes prop and ability to target parent by query selector string.

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/JoshuaToenyes/stout-client.git/'


remove dead code

remove dead code

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/VoiSmart/Rocket.Chat.git/'


Attachment draft

Attachment draft

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

--- lib/attachment.coffee
+++ lib/attachment.coffee
@@ -0,0 +1,66 @@
+#
+React = require 'react'
+$ = React.createElement
+
+Tether = require 'tether/tether'
+
+module.exports = React.createClass
+  displayName: 'Molecule.Attachment'
+
+  getDefaultProps: ->
+    attachment: 'top left'
+    targetAttachment: 'bottom left'
+
+  componentDidMount: ->
+    @root = document.createElement 'DIV'
+    document.body.appendChild @root
+
+    document.addEventListener 'mousedown', @handleCloseRequest
+    document.addEventListener 'focus', @handleCloseRequest, true
+
+  handleCloseRequest: (e) ->
+    return true unless @tether
+
+    node = e.target
+
+    while node != null
+      return true if node == @root || node == @target
+      node = node.parentNode
+
+    @props.onCloseRequest?()
+    true
+
+  attachTo: (target) ->
+    @target = target
+
+    if @tether
+      @tether.setOption target: target
+    else
+      @renderComponent()
+
+      @tether = new Tether
+        element: @root
+        target: target
+        attachment: @props.attachment
+        constraints: @props.constraints
+        targetAttachment: @props.targetAttachment
+
+  componentDidUpdate: ->
+    @renderComponent()
+    @tether.position() if @tether
+
+  componentWillUnmount: ->
+    React.unmountComponentAtNode @root
+
+    @tether.destroy()
+    document.body.removeChild @__root
+    document.removeEventListener 'mousedown', @handleCloseRequest
+    document.removeEventListener 'focus', @handleCloseRequest
+
+  renderComponent: ->
+    if @props.children
+      React.render @props.children, @root
+    else
+      React.unmountComponentAtNode @root
+
+  render: -> null


no admin button visibility test

no admin button visibility test

[#95231438]

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/'


Add ModelProvider event documentation.

Add ModelProvider event documentation.

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/RobotSnacks/stout-orm.git/'


Fixed #2173: Campaigns now update adjacent campaign i18n when saved.

--- server/campaigns/Campaign.coffee
+++ server/campaigns/Campaign.coffee
@@ -1,5 +1,6 @@
 mongoose = require 'mongoose'
 plugins = require '../plugins/plugins'
+log = require 'winston'

 CampaignSchema = new mongoose.Schema(body: String, {strict: false})

@@ -10,4 +11,26 @@
 CampaignSchema.plugin(plugins.TranslationCoveragePlugin)
 CampaignSchema.plugin plugins.PatchablePlugin

+CampaignSchema.statics.updateAdjacentCampaigns = (savedCampaign) ->
+  Campaign = require '../campaigns/Campaign'
+  query = {}
+  query["adjacentCampaigns.#{savedCampaign.get '_id'}"] = {$exists: true}
+  Campaign.find(query).exec (err, campaigns) ->
+    return log.error "Couldn't search for adjacent campaigns to update because of #{err}" if err
+    for campaign in campaigns
+      acs = campaign.get 'adjacentCampaigns'
+      ac = acs[savedCampaign.get '_id']
+      # Let's make sure that we're adding translations, otherwise let's not update yet.
+      # We could possibly remove this; not sure it's worth having.
+      [oldI18NCount, newI18NCount] = [0, 0]
+      oldI18NCount += _.size(translations) for lang, translations of ac.i18n ? {}
+      newI18NCount += _.size(translations) for lang, translations of savedCampaign.get('i18n') ? {}
+      continue unless newI18NCount > oldI18NCount
+      ac.i18n = savedCampaign.get('i18n')
+      # Save without using middleware so that we don't get into a post-save loop.
+      Campaign.findByIdAndUpdate campaign._id, {$set: {adjacentCampaigns: acs}}, (err, doc) ->
+        return log.error "Couldn't save updated adjacent campaign because of #{err}" if err
+
+CampaignSchema.post 'save', -> @constructor.updateAdjacentCampaigns @
+
 module.exports = mongoose.model('campaign', CampaignSchema)


Call #featured only once

Call #featured only once

--- collections/articles.coffee
+++ collections/articles.coffee
@@ -1,9 +1,8 @@
 Backbone = require 'backbone'
+sd = require('sharify').data
 Article = require '../models/article.coffee'
-sd = require('sharify').data

 module.exports = class Articles extends Backbone.Collection
-
   url: "#{sd.POSITRON_URL}/api/articles"

   model: Article
@@ -16,4 +15,6 @@
     @where(tier: 1).slice(0, 4)

   feed: ->
-    @reject (a) => a in @featured()+    featured = @featured()
+    @reject (a) ->
+      a in featured


more modern coffeescript changes

more modern coffeescript 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/flowerbox/flowerbox.git/'


highlight matches in search results

highlight matches in search results

--- lib/fuzzy-finder-view.coffee
+++ lib/fuzzy-finder-view.coffee
@@ -3,6 +3,7 @@
 {$$, SelectListView} = require 'atom-space-pen-views'
 {repositoryForPath} = require './helpers'
 fs = require 'fs-plus'
+{match} = require 'fuzzaldrin'

 module.exports =
 class FuzzyFinderView extends SelectListView
@@ -33,7 +34,22 @@
     @panel?.destroy()

   viewForItem: ({filePath, projectRelativePath}) ->
+
+    # Style matched characters in search results
+    filterQuery = @getFilterQuery()
+
     $$ ->
+
+      highlighter = (str) =>
+        # The match array alternates between unmatched and matched text
+        wrapMe = false
+        for term in match(str, filterQuery)
+          if wrapMe
+            @strong term, class: 'matched-chars'
+          else if term
+            @text term
+          wrapMe = !wrapMe
+
       @li class: 'two-lines', =>
         if (repo = repositoryForPath(filePath))?
           status = repo.getCachedPathStatus(filePath)
@@ -56,10 +72,8 @@
         else
           typeClass = 'icon-file-text'

-        fileBasename = path.basename(filePath)
-
-        @div fileBasename, class: "primary-line file icon #{typeClass}", 'data-name': fileBasename, 'data-path': projectRelativePath
-        @div projectRelativePath, class: 'secondary-line path no-icon'
+        @div class: "primary-line file icon #{typeClass}", -> highlighter(path.basename(filePath))
+        @div class: 'secondary-line path no-icon', -> highlighter(projectRelativePath)

   openPath: (filePath, lineNumber) ->
     if filePath


bug fix

bug fix


missing file

missing file

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

--- src/client/build/mobile.coffee
+++ src/client/build/mobile.coffee
@@ -0,0 +1,7 @@
+{
+  baseUrl: "../"
+  mainConfigFile: "../requirejs-config.js"
+  optimize: "uglify2"
+  name: "mobile"
+  include: "mobile/vendor"
+}


add migration for token-based access indexes

error: pathspec 'server-ce/migrations/7_add_token_indexes.coffee' did not match any file(s) known to git

--- server-ce/migrations/7_add_token_indexes.coffee
+++ server-ce/migrations/7_add_token_indexes.coffee
@@ -0,0 +1,43 @@
+Settings = require "settings-sharelatex"
+fs = require("fs")
+mongojs = require("mongojs")
+ObjectId = mongojs.ObjectId
+db = mongojs(Settings.mongo.url, ['docs','docHistory', 'docHistoryStats'])
+_ = require("underscore")
+async = require("async")
+exec = require("child_process").exec
+bson = require('bson')
+BSON = new bson()
+
+
+handleExit = () ->
+	console.log('Got signal.  Shutting down.')
+
+
+exports.migrate = (client, done=()->) ->
+	console.log ">> Adding indexes for token-based project access: "
+	db.projects.ensureIndex {'tokens.readAndWrite': 1}, {
+    partialFilterExpression: { 'tokens.readAndWrite': { $exists: true } },
+    unique: true,
+    background: true
+  }, (err) ->
+		if err?
+			return done(err)
+		db.projects.ensureIndex {'tokens.readOnly': 1}, {
+			partialFilterExpression: { 'tokens.readOnly': { $exists: true } },
+			unique: true,
+			background: true
+		}, (err) ->
+			if err?
+				return done(err)
+			console.log ">> done adding indexes for token-based project access"
+			done()
+
+
+exports.rollback = (client, done) ->
+	done()
+
+
+process.on 'SIGINT', handleExit
+process.on 'SIGHUP', handleExit
+


GitLab: GenericHandler: base class for all handlers


Avoid race comditions in background completer.

--- pages/vomnibar.coffee
+++ pages/vomnibar.coffee
@@ -206,28 +206,34 @@
 # Sends filter and refresh requests to a Vomnibox completer on the background page.
 #
 class BackgroundCompleter
+  # We increment this counter on each message sent, and ignore responses which arrive too late.
+  @messageId: 0
+
   # - name: The background page completer that you want to interface with. Either "omni", "tabs", or
   # "bookmarks". */
   constructor: (@name) ->
     @filterPort = chrome.runtime.connect({ name: "filterCompleter" })

-  refresh: -> chrome.runtime.sendMessage({ handler: "refreshCompleter", name: @name })
+  refresh: ->
+    BackgroundCompleter.messageId += 1
+    chrome.runtime.sendMessage({ handler: "refreshCompleter", name: @name })

   filter: (query, callback) ->
-    id = Utils.createUniqueId()
+    id = BackgroundCompleter.messageId += 1
     @filterPort.onMessage.addListener (msg) =>
       @filterPort.onMessage.removeListener(arguments.callee)
-      # The result objects coming from the background page will be of the form:
-      #   { html: "", type: "", url: "" }
-      # type will be one of [tab, bookmark, history, domain].
-      results = msg.results.map (result) ->
-        functionToCall = if (result.type == "tab")
-          BackgroundCompleter.completionActions.switchToTab.curry(result.tabId)
-        else
-          BackgroundCompleter.completionActions.navigateToUrl.curry(result.url)
-        result.performAction = functionToCall
-        result
-      callback(results)
+      if id == BackgroundCompleter.messageId
+        # The result objects coming from the background page will be of the form:
+        #   { html: "", type: "", url: "" }
+        # type will be one of [tab, bookmark, history, domain].
+        results = msg.results.map (result) ->
+          functionToCall = if (result.type == "tab")
+            BackgroundCompleter.completionActions.switchToTab.curry(result.tabId)
+          else
+            BackgroundCompleter.completionActions.navigateToUrl.curry(result.url)
+          result.performAction = functionToCall
+          result
+        callback(results)

     @filterPort.postMessage({ id: id, name: @name, query: query })


Fix month

Fix month

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/NatLee/plugin-Akashic-records.git/'


Auto-focus on the modal's input field for creation of new entities in editor. Fixes issue #379

--- app/views/kinds/SearchView.coffee
+++ app/views/kinds/SearchView.coffee
@@ -22,7 +22,7 @@
     'change input#search': 'runSearch'
     'keydown input#search': 'runSearch'
     'click button.new-model-submit': 'makeNewModel'
-    'submit form': 'makeNewModel'
+    'shown.bs.modal #new-model-modal': 'focusOnName'

   getRenderData: ->
     c = super()
@@ -94,3 +94,6 @@
       modal.modal('hide')
       base = document.location.pathname[1..] + '/'
       app.router.navigate(base + (model.get('slug') or model.id), {trigger:true})
+
+  focusOnName: ->
+    @$el.find('#name').focus()


Better validation of inputs

Better validation of inputs

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/'


Added contentType.

Added contentType.

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/'


Implemented Realm entity

Implemented Realm entity

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

--- src/wrathnet/entities/realm.coffee
+++ src/wrathnet/entities/realm.coffee
@@ -0,0 +1,44 @@
+#
+# WrathNet Foundation
+# Copyright (c) 2012 Tim Kurvers <http://wrathnet.org>
+#
+# World of Warcraft client foundation written in JavaScript, enabling
+# development of expansion-agnostic clients, bots and other useful tools.
+#
+# The contents of this file are subject to the MIT License, under which
+# this library is licensed. See the LICENSE file for the full license.
+#
+
+# Denotes a realm
+class WrathNet.entities.Realm
+
+  # Creates a new realm
+  constructor: ->
+
+    # Holds host, port and address
+    @_host = null
+    @_port = NaN
+    @_address = null
+
+  # Short string representation of this realm
+  toString: ->
+    return '[Realm; Address: ' + @_address + ']'
+
+  # Retrieves host for this realm
+  @getter 'host', ->
+    return @_host
+
+  # Retrieves port for this realm
+  @getter 'port', ->
+    return @_port
+
+  # Retrieves address for this realm
+  @getter 'address', ->
+    return @_address
+
+  # Sets address for this realm
+  @setter 'address', (address) ->
+    @_address = address
+    parts = @_address.split(':')
+    @_host = parts[0] || null
+    @_port = parts[1] || NaN


STL/dom the $ function unit tests

STL/dom the $ function unit tests

error: pathspec 'stl/dom/test/unit/main_test.coffee' did not match any file(s) known to git

--- stl/dom/test/unit/main_test.coffee
+++ stl/dom/test/unit/main_test.coffee
@@ -0,0 +1,86 @@
+#
+# The `$` function unit tests
+#
+# Copyright (C) 2011 Nikolay Nemshilov
+#
+{describe, assert, load} = require('../test_helper')
+
+server.respond "/main.html": """
+
+
+
+
+
+
+

+
+
+"""
+
+dom = ->
+  load "/main.html", this, (d) -> d
+
+
+describe '$', module,
+
+  'css search':
+    topic: dom
+
+    'should find elements by a css-rule': ($)->
+      result = $('#test')
+
+      assert.isTrue result instanceof $.Search
+      assert.equal  result.length, 1
+      assert.equal  result[0].attr('id'), 'test'
+
+    'should return an empty search when nothing found': ($)->
+      result = $('#non-existing')
+
+      assert.isTrue result instanceof $.Search
+      assert.equal  result.length, 1
+
+    # FIXME: the `window.window == window` hack doesn't work in jsdom
+    #        need to figure out something else
+    # 'window wrapping':
+    #       topic: dom
+    #
+    #       'should return a window wrapper for a window': ($)->
+    #         win = $(this.window)
+    #
+    #         assert.isTrue win instanceof $.Window
+    #         assert.isTrue     win._ is this.window
+    #
+    #       'should return the same window wrapper back': ($)->
+    #         win = $(this.window)
+    #
+    #         assert.isTrue $(win) is win
+
+  'document wrapping':
+    topic: dom
+
+    'should wrap a document': ($)->
+      doc = $(this.document)
+
+      assert.isTrue doc instanceof $.Document
+      assert.same   doc._, this.document
+
+    'should return the same wrapper if already wrapped': ($)->
+      doc = $(this.document)
+
+      assert.same doc, $(doc)
+
+  'element wrapping':
+    topic: dom
+
+    'should return a wrapper for a dom-element': ($)->
+      div = this.document.getElementById('test')
+      element = $(div)
+
+      assert.isTrue element instanceof $.Element
+      assert.same   element._, div
+
+    'should return the same wrapper if an element is already wrapped': ($)->
+      div = this.document.getElementById('test')
+      element = $(div)
+
+      assert.same element, $(element)


Make sure line is < 80 char

Make sure line is < 80 char

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/clochix/cozy-home.git/'


Set up Chai assertions.

Set up Chai assertions.

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

--- test/features/support/setup.coffee
+++ test/features/support/setup.coffee
@@ -0,0 +1,3 @@
+module.exports = ->
+  chai = require 'chai'
+  @World.prototype.expect = chai.expect


added keymaps file

added keymaps file

error: pathspec 'keymaps/keymaps.cson' did not match any file(s) known to git

--- keymaps/keymaps.cson
+++ keymaps/keymaps.cson
@@ -0,0 +1,3 @@
+'atom-text-editor':
+  'alt-p e': 'perforce:edit'
+  'alt-p a': 'perforce:add'


Add deploy script to deploy from bufferbot-slack

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

--- scripts/deploy.coffee
+++ scripts/deploy.coffee
@@ -0,0 +1,40 @@
+# Description:
+#  Kick of a jenkins deploy build
+#
+# Commands:
+#   hubot deploy <target> - Deploy master to the given envirnonment
+#
+
+jenkinsURL           = process.env.HUBOT_CIBOT_URL
+jenkinsToken         = process.env.HUBOT_CIBOT_BUILD_TOKEN
+jenkinsBuildJobName  = process.env.HUBOT_CIBOT_BUILD_JOB_NAME
+
+startBuild = (msg, target, branch = "master") ->
+    if !target
+      #description = "Requested by #{msg.message.user.name} in #{msg.message.user.room}"
+      msg.send "I'm sorry. You need to provide an elastic beanstalk Buffer target"
+    else
+      msg.send  "Branch: #{branch}"
+      msg.send  "Target: #{target}"
+
+      jobUrl = "#{jenkinsURL}/buildByToken/buildWithParameters?job=#{jenkinsBuildJobName}&token=#{jenkinsToken}&Target=#{target}&Branch=#{branch}"
+      msg.http(jobUrl)
+        .get() (err, res, body) ->
+          if body.length > 2000
+            msg.send "Whoops, I can't deploy to #{target}"
+          else
+            msg.send "Great, deploying #{branch} to #{target}"
+
+
+module.exports = (robot) ->
+
+  robot.respond /deploy\s*([a-zA-Z0-9-/']+\s)(to\s+)?(.+)/i, (msg) ->
+    branch     = msg.match[1] or null
+    target     = msg.match[3] or null
+    branch     = branch.replace /^\s+|\s+$/g, ""
+    startBuild(msg, target, branch)
+
+  robot.respond /deploy\s*(.+)/i, (msg) ->
+    target     = msg.match[1] or null
+    if !/.+\s.+/i.test(target)
+      startBuild(msg, target)


Show error when no score selected

Show error when no score selected

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/bmedx/modulestore.git/'


Tests:IDE:Workspace: fixed deleteWorkspace helper.

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/'


Tests: Make login optional on postActivity.

--- tests/src/helpers/helpers.coffee
+++ tests/src/helpers/helpers.coffee
@@ -66,9 +66,10 @@
     @doLogin browser, user

-  postActivity: (browser) ->
+  postActivity: (browser, shouldBeginTest = yes) ->

-    @beginTest(browser)
+    if shouldBeginTest
+      @beginTest(browser)

     browser.click '[testpath=public-feed-link]'


prevent sass updates from reloading page

--- app/templates/gulpfile.coffee
+++ app/templates/gulpfile.coffee
@@ -76,7 +76,7 @@
     .pipe sass({errLogToConsole: true})
     .pipe(sourcemaps.write('./'))
     .pipe gulp.dest(conf.path.dev.css)
-    .pipe reload({stream: true})
+    .pipe bs.stream match: '**/*.css'


reexport bs-modal-handler

reexport bs-modal-handler

error: pathspec 'app/components/bs-modal-handler/component.coffee' did not match any file(s) known to git

--- app/components/bs-modal-handler/component.coffee
+++ app/components/bs-modal-handler/component.coffee
@@ -0,0 +1,2 @@
+`import BsModalHandlerComponent from 'ember-cli-bscomponents/components/bs-modal-handler/component'`
+`export default BsModalHandlerComponent`


fix: reset targetFolder when reseting oauth tokens

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-tde-exporter.git/'


Fix max/avg/med/min selection on serial history graph

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-reports.git/'


pipe info, warn and error to console by default

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/'


Removes a console.log line

Removes a console.log line

Signed-off-by: Akash Manohar J <e4cf979cf717fd295f4e4edc427ee1aee78fa7dc@akash.im>

--- app/assets/javascripts/backbone/helpers/channels.js.coffee
+++ app/assets/javascripts/backbone/helpers/channels.js.coffee
@@ -21,7 +21,6 @@
     else
       $channel_elements = $("#channels .ui-tabs-panel")
       for el in $channel_elements
-        console.log "appending to", $(el).attr('id')
         activity = new Kandan.Models.Activity(activity_attributes)
         activity_view  = new Kandan.Views.ShowActivity({activity: activity})
         $(el).append(activity_view.render().el)


Activity: fix the settings button logic

Activity: fix the settings button logic


Fix Unittest

Fix Unittest

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/BennySamir/Welcomescreen.git/'


Fix JS exception when closing an event, refs #405

--- client/app/lib/popover_view.coffee
+++ client/app/lib/popover_view.coffee
@@ -18,8 +18,9 @@

     close: ->
-        @$popover.remove()
-        @$popover = null
+        if @$popover?
+            @$popover.remove()
+            @$popover = null
         @target.data 'popover', undefined
         @remove()


Removed uses of 'char' from writer switch

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/thestartcup/jsonc.git/'


sample data for a planned package-set-selector package

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

--- package_sets.cson
+++ package_sets.cson
@@ -0,0 +1,86 @@
+# todo: screen out dependencies
+
+always: [
+    atom-keyboard-macros
+    autocomplete-paths
+    clipboard-plus
+    editorconfig
+    emacs-plus
+    "export-html"
+    file-icons
+    flex-tool-bar
+    jumpy
+    last-cursor-position
+    minimap
+    project-manager
+    script
+    shell-it
+    slickedit-select
+    sort-lines
+    terminal-plus
+    tool-bar
+    open-unsupported-files
+]
+
+python: [
+    Hydrogen
+    MagicPython
+    autocomplete-python
+    linter
+    linter-pycodestyle
+    linter-pydocstyle
+    python-isort
+    python-snippets
+    python-tools
+    python-yapf
+    pythonic-atom
+    # specify disable language-python??
+]
+
+javascript: [
+    atom-ternjs
+    language-javascript-jsx
+]
+
+# active-editor-info
+# advanced-open-file
+# atom-beautify
+# atom-live-grammar-reload
+#
+# autoclose-html
+#
+# busy-signal
+#
+# custom-folds
+# disable-keybindings
+# django-templates
+# go-plus
+# goto
+# grammar-mode
+# intentions
+# jumpy
+# language-babel
+# language-forth
+# language-markdown
+# language-mips
+# language-powershell
+# language-svg
+# language-utl
+#
+# linter
+# linter-coffeescript
+# linter-eslint
+# linter-gcc
+# linter-jsonlint
+# linter-less
+# linter-phpcs
+# linter-shellcheck
+# linter-tidy
+# linter-ui-default
+# linter-xmllint
+# minimap-git-diff
+# minimap-linter
+# open-html-in-browser
+# php-debug
+# split-diff
+# symbol-quick-pane


Implemented world packet

Implemented world packet

error: pathspec 'src/wrathnet/expansions/wotlk/net/world-packet.coffee' did not match any file(s) known to git

--- src/wrathnet/expansions/wotlk/net/world-packet.coffee
+++ src/wrathnet/expansions/wotlk/net/world-packet.coffee
@@ -0,0 +1,33 @@
+#
+# WrathNet Foundation
+# Copyright (c) 2012 Tim Kurvers <http://wrathnet.org>
+#
+# World of Warcraft client foundation written in JavaScript, enabling
+# development of expansion-agnostic clients, bots and other useful tools.
+#
+# The contents of this file are subject to the MIT License, under which
+# this library is licensed. See the LICENSE file for the full license.
+#
+
+# Denotes a world packet
+class WrathNet.expansions.wotlk.net.WorldPacket extends WrathNet.net.Packet
+
+  # Imports
+  ObjectUtil = WrathNet.utils.ObjectUtil
+  WorldOpcode = WrathNet.expansions.wotlk.enums.WorldOpcode
+
+  # Header sizes in bytes for both incoming and outgoing packets
+  @HEADER_SIZE_INCOMING = 4
+  @HEADER_SIZE_OUTGOING = 6
+
+  # Opcode sizes in bytes for both incoming and outgoing packets
+  @OPCODE_SIZE_INCOMING = 2
+  @OPCODE_SIZE_OUTGOING = 4
+
+  # Retrieves the name of the opcode for this packet (if available)
+  @getter 'opcodeName', ->
+    return ObjectUtil.keyByValue(WorldOpcode, @opcode)
+
+  # Header size in bytes (dependent on packet origin)
+  @getter 'headerSize', ->
+    return if @outgoing then @constructor.HEADER_SIZE_OUTGOING else @constructor.HEADER_SIZE_INCOMING


Add a script for getting Captain Quail from Hubot.

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

--- scripts/captain-quail.coffee
+++ scripts/captain-quail.coffee
@@ -0,0 +1,34 @@
+# Description:
+#   The Adventures of Captain Quail, now in you chat!
+#
+# Dependencies:
+#   "htmlparser": "1.7.6"
+#   "soupselect": "0.2.0"
+#
+# Configuration:
+#   None
+#
+# Commands:
+#   hubot cq - The latest Adventures of Captain Quail
+#
+# Author:
+#   phildini
+
+htmlparser = require "htmlparser"
+Select = require("soupselect").select
+
+module.exports = (robot) ->
+    robot.respond /cq/i, (msg) ->
+        msg.http("http://www.captainquail.com/comic/")
+            .get() (err, res, body) ->
+                handler = new htmlparser.DefaultHandler()
+                parser = new htmlparser.Parser(handler)
+                parser.parseComplete(body)
+
+                img = Select handler.dom, "img.comic"
+                title = Select handler.dom, "a.content-link"
+                link = title[0].attribs
+                comic = img[0].attribs
+
+                msg.send link.href
+                msg.send comic.alt


Script to clean up MTurk by deleting old HITs after backup

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

--- turk/saveLocallyAndDispose.coffee
+++ turk/saveLocallyAndDispose.coffee
@@ -0,0 +1,99 @@
+'''
+Get all approved assignments, save their info to Mongo, then remove from Amazon
+
+This script doesn't approve or apply bonuses itself, it's sole purpose is
+Amazon cleanup.
+'''
+async = require 'async'
+argv = require('yargs')
+        .boolean('p').alias('production','p')
+        .describe('production', 'Run on production.')
+        .boolean('e').alias('empty-only', 'e')
+        .describe('e', 'Only dispose reviewable HITs without any assignments.')
+        .help('h').alias('h', 'help')
+        .argv
+
+mongoose = require 'mongoose'
+config = require 'config'
+db_server = 'mongodb://' + config.get('db.host') + '/' + config.get('db.name')
+mongoose.connect db_server
+db = mongoose.connection
+TurkBackup = require '../models/turkBackup.js'
+
+# Use credentials file from Boto
+PropertiesReader = require 'properties-reader'
+boto = PropertiesReader('/home/ec2-user/.boto')
+
+creds =
+  accessKey: boto.get('Credentials.aws_access_key_id')
+  secretKey: boto.get('Credentials.aws_secret_access_key')
+
+mturk = require('mturk')({creds: creds, sandbox: !argv.production})
+
+main = () ->
+  getReviewableHITs()
+
+asArr = (res) ->
+  if not res then return []
+  if (res instanceof Array) then res else [res]
+
+# Wrapper for recursive function
+getReviewableHITs = (page=1) ->
+  pageSize = 10
+  mturk.GetReviewableHITs(
+    {PageSize:pageSize, PageNumber:page},
+    (err, result) ->
+      if err then return console.error err
+      if result.NumResults is 0
+        return db.close()
+      console.log(result)
+      hits = asArr(result.HIT)
+      async.forEach(hits, saveAssignments, (err) ->
+        if err
+          console.error err
+          db.close()
+        # If there were more items left, run again
+        if (result.TotalNumResults > (page * pageSize))
+          page = page + 1
+          setTimeout((()->getReviewableHITs(page)), 4000)
+        else
+          db.close()
+      )
+  )
+
+saveAssignments = (hit, cb) ->
+  mturk.GetAssignmentsForHIT({ HITId: hit.HITId, PageSize:100 },
+  (err, result) ->
+    if err then return cb(err)
+    if not result.Assignment
+      # HIT doesn't have completed assignments
+      mturk.DisposeHIT({ HITId: hit.HITId}, (err, result) ->
+        if not err then console.log "Empty HIT #{hit.HITId} was disposed."
+        return cb(err)
+      )
+      return
+    # Don't go any further if the emty-only flag is up
+    if argv.e then return cb(null)
+    assignments = asArr(result.Assignment)
+    async.forEach(assignments, saveAssignment, (err) ->
+      if err then return cb(err)
+      # The assignments seem to have saved properly, so dispose of the HIT
+      mturk.DisposeHIT({ HITId: hit.HITId}, (err, result) ->
+        if not err then console.log "#{hit.HITId} saved and disposed."
+        cb(err)
+      )
+    )
+  )
+
+# Save an Individual Assignment to Mongo
+saveAssignment = (assignment, cb) ->
+  if assignment.AssignmentStatus not in ['Approved', 'Rejected']
+    console.log assignment
+    return cb("#{assignment.AssignmentId} does not have an expected status.
+    Don't run this script until all assignments are reviewed.")
+  assignment._id = assignment.AssignmentId
+  assignment.sandbox = true
+  turkBackup = new TurkBackup(assignment)
+  turkBackup.save((err, res) -> cb(err))
+
+main()


Fix the failing sendSync

Fix the failing sendSync

--- atom/renderer/api/lib/remote.coffee
+++ atom/renderer/api/lib/remote.coffee
@@ -119,7 +119,11 @@

 # Browser calls a callback in renderer.
 ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) ->
-  callbacksRegistry.apply id, metaToValue(args)
+  # Delay the callback to next tick in case the browser is still in the middle
+  # of sending this message while the callback sends a sync message to browser,
+  # which can fail sometimes.
+  setImmediate ->
+    callbacksRegistry.apply id, metaToValue(args)

 # A callback in browser is released.
 ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) ->


Additional unit tests for domain completer.

--- tests/unit_tests/completion_test.coffee
+++ tests/unit_tests/completion_test.coffee
@@ -54,11 +54,11 @@
       @history2 = { url: "a.com", lastVisitTime: 10 }
       history = [@history1, @history2]
       @onVisitedListener = null
-      @onVisitRemovedListerner = null
+      @onVisitRemovedListener = null
       global.chrome.history =
         search: (options, callback) -> callback(history)
         onVisited: { addListener: (@onVisitedListener) => }
-        onVisitRemoved: { addListener: (@onVisitRemovedListerner) => }
+        onVisitRemoved: { addListener: (@onVisitRemovedListener) => }
       HistoryCache.reset()

     should "store visits sorted by url ascending", ->
@@ -84,7 +84,7 @@
       HistoryCache.use (@results) =>
       assert.arrayEqual [@history2, @history1], @results
       toRemove = { urls: [ "x.com" ], allHistory: false }
-      @onVisitRemovedListerner(toRemove)
+      @onVisitRemovedListener(toRemove)
       HistoryCache.use (@results) =>
       assert.arrayEqual [@history2, @history1], @results

@@ -92,7 +92,7 @@
       HistoryCache.use (@results) =>
       assert.arrayEqual [@history2, @history1], @results
       toRemove = { urls: [ "a.com" ], allHistory: false }
-      @onVisitRemovedListerner(toRemove)
+      @onVisitRemovedListener(toRemove)
       HistoryCache.use (@results) =>
       assert.arrayEqual [@history1], @results

@@ -100,7 +100,7 @@
       HistoryCache.use (@results) =>
       assert.arrayEqual [@history2, @history1], @results
       toRemove = { allHistory: true }
-      @onVisitRemovedListerner(toRemove)
+      @onVisitRemovedListener(toRemove)
       HistoryCache.use (@results) =>
       assert.arrayEqual [], @results

@@ -132,7 +132,11 @@
     @history2 = { title: "history2", url: "http://history2.com", lastVisitTime: hours(1) }

     stub(HistoryCache, "use", (onComplete) => onComplete([@history1, @history2]))
-    global.chrome.history = { onVisited: { addListener: -> }, onVisitRemoved: { addListener: -> } }
+    @onVisitedListener = null
+    @onVisitRemovedListener = null
+    global.chrome.history =
+      onVisited: { addListener: (@onVisitedListener) => }
+      onVisitRemoved: { addListener: (@onVisitRemovedListener) => }
     stub(Date, "now", returns(hours(24)))

     @completer = new DomainCompleter()
@@ -150,6 +154,25 @@
   should "returns no results when there's more than one query term, because clearly it's not a domain", ->
     assert.arrayEqual [], filterCompleter(@completer, ["his", "tory"])

+  should "remove 1 matching domain entry", ->
+    # Force installation of `@onVisitRemovedListener`
+    @history2.lastVisitTime = hours(3) and filterCompleter(@completer, ["story"])
+    @onVisitRemovedListener { allHistory: false, urls: [ @history2.url ] }
+    assert.equal "history1.com", filterCompleter(@completer, ["story"])[0].url
+
+  should "remove 2 (both) matching domain entries", ->
+    # Force installation of `@onVisitRemovedListener`
+    @history2.lastVisitTime = hours(3) and filterCompleter(@completer, ["story"])
+    @onVisitRemovedListener { allHistory: false, urls: [ @history2.url ] }
+    @onVisitRemovedListener { allHistory: false, urls: [ @history1.url ] }
+    assert.isTrue filterCompleter(@completer, ["story"]).length == 0
+
+  should "remove *all* domain entries", ->
+    # Force installation of `@onVisitRemovedListener`
+    @history2.lastVisitTime = hours(3) and filterCompleter(@completer, ["story"])
+    @onVisitRemovedListener { allHistory: true }
+    assert.isTrue filterCompleter(@completer, ["story"]).length == 0
+
 context "tab completer",
   setup ->
     @tabs = [


itemsのテスト追加

itemsのテスト追加

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/april418/riot-table.git/'


Update ForkModal.coffee. Unset i18nCoverage on Fork

--- app/views/editor/ForkModal.coffee
+++ app/views/editor/ForkModal.coffee
@@ -29,6 +29,7 @@
     newModel.unset 'original'
     newModel.unset 'parent'
     newModel.unset 'i18n'
+    newModel.unset 'i18nCoverage'
     newModel.set 'commitMessage', "Forked from #{@model.get('name')}"
     newModel.set 'name', @$el.find('#fork-model-name').val()
     if @model.schema().properties.permissions


Update tests to swtich from underscore to lodash

--- test/extractor.coffee
+++ test/extractor.coffee
@@ -1,5 +1,5 @@
 suite 'Extractor', ->
-  _ = require('underscore')
+  _ = require('lodash')
   extractor = require("../src/extractor")

   checkFixture = (site, fields) ->


iエラーハンドリング

iエラーハンドリング

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/opst-kubo/opstbot.git/'


update token

update token

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-doctool-tagging.git/'


bug fix

bug fix

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/'


Make focus state distinct until changed on Focusable objects

--- src/focusable.coffee
+++ src/focusable.coffee
@@ -8,6 +8,7 @@
       @$focusContext
         .flatMapLatest((context) -> context?.$focusedObject)
         .map((focusedObject) => focusedObject is this)
+        .distinctUntilChanged()

   focus: ->
     throw new Error("Object must be assigned a focusContext to be focus") unless @focusContext


Remove logs from spec

Remove logs from spec

--- spec/app/editor-spec.coffee
+++ spec/app/editor-spec.coffee
@@ -277,12 +277,10 @@
       session0 = editor.activeEditSession

       buffer1 = new Buffer(require.resolve('fixtures/sample.txt'))
-      console.log "set buffer 1"
       editor.setBuffer(buffer1)
       session1 = editor.activeEditSession

       buffer2 = new Buffer(require.resolve('fixtures/two-hundred.txt'))
-      console.log "set buffer 2"
       editor.setBuffer(buffer2)
       session2 = editor.activeEditSession


auth worker: let guests authenticate to group channels

if the permission grid says that they should be allowed to "read activity" then they should be able to see realtime updates too.  So let them get hold of a secret channel in that case.


<model> Driver - Backbone model.

<model> Driver - Backbone model.

error: pathspec 'client/app/models/driver.coffee' did not match any file(s) known to git

--- client/app/models/driver.coffee
+++ client/app/models/driver.coffee
@@ -0,0 +1,25 @@
+
+module.exports = class Driver extends Backbone.RelationalModel
+	relations: [
+			type: Backbone.HasMany
+			key: 'sensor'
+			relatedModel: 'Sensor'
+			autoFetch: false
+			includeInJSON: Backbone.Model.prototype.idAttribute
+			collectionType: 'SensorCollection'
+		,
+			type: Backbone.HasMany
+			key: 'actuator'
+			relatedModel: 'Actuator'
+			autoFetch: false
+			includeInJSON: Backbone.Model.prototype.idAttribute
+			collectionType: 'ActuatorCollection'
+
+	]
+
+	urlRoot: 'drivers'
+
+    defaults: ->
+        name: 		''
+		isSensor: 	false
+		isActuator: false


Added logging for when no images found during periodic check

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/chorrell/hubot-imgapi.git/'


Add snipets for commonly-used wiki-links

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/ylansegal/dotfiles.git/'


fix broken JS for filter form

fix broken JS for filter form

Something changed the form's ID to go from 'q' to 'new_q'.
That's fine; this is a better solution anyway.

--- app/assets/javascripts/active_admin/pages/application.js.coffee
+++ app/assets/javascripts/active_admin/pages/application.js.coffee
@@ -12,7 +12,7 @@
   $('.dropdown_button').popover()

   # Filter form: don't send any inputs that are empty
-  $('#q_search').submit ->
+  $('.filter_form').submit ->
     $(@).find(':input').filter(-> @value is '').prop 'disabled', true

   # Filter form: for filters that let you choose the query method from


Add editor component resize spec

Add editor component resize spec

--- spec/editor-component-spec.coffee
+++ spec/editor-component-spec.coffee
@@ -1265,6 +1265,14 @@
         wrapperView.show()
         expect(node.querySelector('.cursor').style['-webkit-transform']).toBe "translate3d(#{9 * charWidth}px, 0px, 0px)"

+  describe "when the editor component is resized", ->
+    it "updates the size in the editor model", ->
+      originalHeight = editor.getHeight()
+      fourLinesHeight = 4 * editor.getLineHeightInPixels()
+      node.style.height = "#{originalHeight - fourLinesHeight}px"
+      component.forceUpdate()
+      expect(editor.getHeight()).not.toBe originalHeight
+
   buildMouseEvent = (type, properties...) ->
     properties = extend({bubbles: true, cancelable: true}, properties...)
     event = new MouseEvent(type, properties)


Test multiple tab stops per line

Test multiple tab stops per line

--- spec/tokenized-buffer-spec.coffee
+++ spec/tokenized-buffer-spec.coffee
@@ -346,24 +346,24 @@

       it "aligns the hard tabs to the correct tab stop column", ->
         buffer.setText """
-          1\t2
-          12\t3
-          123\t4
+          1\t2 \t3\t4
+          12\t3  \t4\t5
+          123\t4   \t5\t6
         """

         tokenizedBuffer.setTabLength(4)
         fullyTokenize(tokenizedBuffer)

-        expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1   2"
-        expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12  3"
-        expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4"
+        expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1   2   3   4"
+        expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12  3   4   5"
+        expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4       5   6"

         tokenizedBuffer.setTabLength(2)
         fullyTokenize(tokenizedBuffer)

-        expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1 2"
-        expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12  3"
-        expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4"
+        expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1 2   3 4"
+        expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12  3   4 5"
+        expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4     5 6"

   describe "when the buffer contains surrogate pairs", ->
     beforeEach ->


Fix parser error test

Fix parser error test

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/'


Report errors with no stack when loading packages

--- src/app/atom-package.coffee
+++ src/app/atom-package.coffee
@@ -28,7 +28,7 @@
       else
         @requireMainModule()
     catch e
-      console.warn "Failed to load package named '#{@name}'", e.stack
+      console.warn "Failed to load package named '#{@name}'", e.stack ? e
     this

   activate: ({immediate}={}) ->


JSONヘルパークラスを追加

JSONヘルパークラスを追加

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

--- src/coffee/JsonUtils.coffee
+++ src/coffee/JsonUtils.coffee
@@ -0,0 +1,23 @@
+class JsonUtils
+	###*
+    * JSONをソートするための関数です。JSON.sort()の引数に渡して使います。例：json.sort(JsonUtils.sort_by("index", false, parseInt))
+    * @param {Object} field ソートの基準にするプロパティ
+    * @param {Boolean} reverse 昇順
+    * @param {Function} primer 型
+	###
+	@sort_by: (field, reverse, primer) ->
+		if (reverse)
+			reverse = -1
+		else
+			reverse = 1
+		return (a, b) ->
+			a = a[field]
+			b = b[field]
+			if typeof(primer) != "undefined"
+				a = primer(a)
+				b = primer(b)
+			if (a < b)
+				return reverse * -1
+			if (a > b)
+				return reverse * 1
+			return 0


need to pass through collectionSynced

need to pass through collectionSynced

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/andrhamm/Singularity.git/'


delete unnecessary file

delete unnecessary 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/RobertsGroza/kakimasu.git/'


avoid multiple template set

avoid multiple template set

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/VoiSmart/Rocket.Chat.git/'


Reinstate event.data in asset reveal until jsmin is deprecated

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/'


progress on who to follow feature

progress on who to follow feature

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/Snitzle/hummingbird.git/'


Level editor only folds in ThangType components into Thang component configs if the level is type 'hero'.

--- app/views/editor/level/thangs/LevelThangEditView.coffee
+++ app/views/editor/level/thangs/LevelThangEditView.coffee
@@ -42,7 +42,8 @@
       supermodel: @supermodel
       level: @level
       world: @world
-      thangType: thangType
+
+    if @level.get('type') is 'hero' then options.thangType = thangType

     @thangComponentEditView = new ThangComponentsEditView options
     @listenTo @thangComponentEditView, 'components-changed', @onComponentsChanged


before pull with cozy/development

before pull with cozy/development

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/clochix/cozy-home.git/'


adding Object#isArray

adding Object#isArray

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

--- src/object_extensions.coffee
+++ src/object_extensions.coffee
@@ -0,0 +1,8 @@
+###*
+* Checks whether an object is an array.
+*
+* @type Object
+* @returns A boolean expressing whether the object is an instance of Array
+###
+Object::isArray = ->
+  return Object.prototype.toString.call(this) == '[object Array]'


fixed error

fixed error

Signed-off-by: iAladdin <679e1abc26a0ea5d010d9e2ef227195b64a25a15@me.com>

--- app/locale/zh-HANS.coffee
+++ app/locale/zh-HANS.coffee
@@ -792,7 +792,7 @@
 #    system: "System"
 #    systems: "Systems"
     component: "组件"
-   components: "组件"
+    components: "组件"
     thang: "物品"
     thangs: "物品"
 #    level_session: "Your Session"


no longer pulling Manifest in

no longer pulling Manifest in

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/curlee/Appnostic.git/'


Teamwork: Implemented query handler.

Teamwork: Implemented query handler.

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/'


client: support: getChatlioKey util added


ChatMessagePane: Don't show onboarding view if there is a user message in chat.


Added world opcodes

Added world opcodes

error: pathspec 'src/wrathnet/expansions/wotlk/enums/world-opcode.coffee' did not match any file(s) known to git

--- src/wrathnet/expansions/wotlk/enums/world-opcode.coffee
+++ src/wrathnet/expansions/wotlk/enums/world-opcode.coffee
@@ -0,0 +1,93 @@
+#
+# WrathNet Foundation
+# Copyright (c) 2012 Tim Kurvers <http://wrathnet.org>
+#
+# World of Warcraft client foundation written in JavaScript, enabling
+# development of expansion-agnostic clients, bots and other useful tools.
+#
+# The contents of this file are subject to the MIT License, under which
+# this library is licensed. See the LICENSE file for the full license.
+#
+
+# World opcodes
+class WrathNet.expansions.wotlk.enums.WorldOpcode
+
+  @CMSG_CHAR_ENUM                     = 0x0037
+
+  @SMSG_CHAR_ENUM                     = 0x003B
+
+  @CMSG_PLAYER_LOGIN                  = 0x003D
+
+  @SMSG_CHARACTER_LOGIN_FAILED        = 0x0041
+  @SMSG_LOGIN_SETTIMESPEED            = 0x0042
+
+  @SMSG_CONTACT_LIST                  = 0x0067
+
+  @CMSG_MESSAGE_CHAT                  = 0x0095
+  @SMSG_MESSAGE_CHAT                  = 0x0096
+
+  @SMSG_UPDATE_OBJECT                 = 0x00A9
+
+  @SMSG_MONSTER_MOVE                  = 0x00DD
+
+  @SMSG_TUTORIAL_FLAGS                = 0x00FD
+
+  @SMSG_INITIALIZE_FACTIONS           = 0x0122
+
+  @SMSG_SET_PROFICIENCY               = 0x0127
+
+  @SMSG_ACTION_BUTTONS                = 0x0129
+  @SMSG_INITIAL_SPELLS                = 0x012A
+
+  @SMSG_SPELL_START                   = 0x0131
+  @SMSG_SPELL_GO                      = 0x0132
+
+  @SMSG_BINDPOINT_UPDATE              = 0x0155
+
+  @SMSG_ITEM_TIME_UPDATE              = 0x01EA
+
+  @SMSG_AUTH_CHALLENGE                = 0x01EC
+  @CMSG_AUTH_PROOF                    = 0x01ED
+  @SMSG_AUTH_RESPONSE                 = 0x01EE
+
+  @SMSG_COMPRESSED_UPDATE_OBJECT      = 0x01F6
+
+  @SMSG_ACCOUNT_DATA_TIMES            = 0x0209
+
+  @SMSG_LOGIN_VERIFY_WORLD            = 0x0236
+
+  @SMSG_SPELL_NON_MELEE_DAMAGE_LOG    = 0x0250
+
+  @SMSG_UPDATE_WORLD_STATE            = 0x02C3
+
+  @SMSG_WEATHER                       = 0x02F4
+
+  @MSG_SET_DUNGEON_DIFFICULTY         = 0x0329
+
+  @SMSG_UPDATE_INSTANCE_OWNERSHIP     = 0x032B
+
+  @SMSG_INSTANCE_DIFFICULTY           = 0x033B
+
+  @SMSG_MOTD                          = 0x033D
+
+  @SMSG_TIME_SYNC_REQ                 = 0x0390
+
+  @SMSG_FEATURE_SYSTEM_STATUS         = 0x03C9
+
+  @SMSG_SERVER_BUCK_DATA              = 0x041D
+  @SMSG_SEND_UNLEARN_SPELLS           = 0x041E
+
+  @SMSG_LEARNED_DANCE_MOVES           = 0x0455
+
+  @SMSG_ALL_ACHIEVEMENT_DATA          = 0x047D
+
+  @SMSG_POWER_UPDATE                  = 0x0480
+
+  @SMSG_AURA_UPDATE_ALL               = 0x0495
+  @SMSG_AURA_UPDATE                   = 0x0496
+
+  @SMSG_EQUIPMENT_SET_LIST            = 0x04BC
+
+  @SMSG_TALENTS_INFO                  = 0x04C0
+
+  @MSG_SET_RAID_DIFFICULTY            = 0x04EB


First draft implementation to update stock information in master project of a marketplace.

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

--- src/coffee/retailer2master.coffee
+++ src/coffee/retailer2master.coffee
@@ -0,0 +1,129 @@
+_ = require('underscore')._
+Config = require("../config")
+StockXmlImport = require("../lib/stockxmlimport").StockXmlImport
+Rest = require('sphere-node-connect').Rest
+Q = require('q')
+ProgressBar = require 'progress'
+
+Config.timeout = 120000
+stockxmlimport = new StockXmlImport Config
+
+rProjectKey = ""
+rClientId = ""
+rClientSecret = ""
+process.argv.forEach (val, index, array) ->
+  rProjectKey = val if index is 2
+  rClientId = val if index is 3
+  rClientSecret = val if index is 4
+
+rRest = new Rest config: {
+  project_key: rProjectKey
+  client_id: rClientId
+  client_secret: rClientSecret
+}
+
+retailerChannelInMaster = () =>
+  deferred = Q.defer()
+  stockxmlimport.rest.GET "/channels?query=" + encodeURIComponent("key=\"#{rProjectKey}\""), (error, response, body) ->
+    if error
+      deferred.reject "Error: " + error
+      return deferred.promise
+    if response.statusCode == 200
+      channels = JSON.parse(body).results
+      if channels.length is 1
+        deferred.resolve channels[0].id
+        return deferred.promise
+    # let's create the channel for the retailer in master project
+    c =
+      key: rProjectKey
+    stockxmlimport.rest.POST "/channels", JSON.stringify(c), (error, response, body) ->
+      if error
+        deferred.reject "Error: " + error
+      else if response.statusCode == 201
+        id = JSON.parse(body).id
+        deferred.resolve id
+      else
+        deferred.reject "Problem: " + body
+  deferred.promise
+
+retailerProducts = () ->
+  deferred = Q.defer()
+  rRest.GET "/products?limit=0", (error, response, body) ->
+    if error
+      deferred.reject "Error: " + error
+    else if response.statusCode != 200
+      deferred.reject "Problem: " + body
+    else
+      retailerProducts = JSON.parse(body).results
+      deferred.resolve retailerProducts
+  deferred.promise
+
+stocks = (rest) ->
+  deferred = Q.defer()
+  rest.GET "/inventory?limit=0", (error, response, body) ->
+    if error
+      deferred.reject "Error: " + error
+    else if response.statusCode != 200
+      deferred.reject "Problem: " + body
+    else
+      stocks = JSON.parse(body).results
+      deferred.resolve stocks
+  deferred.promise
+
+match = (masterStocks, retailerProducts) ->
+  master2retailer = {}
+  for p in retailerProducts
+    _.extend(master2retailer, matchVariant(p.masterData.current.masterVariant))
+    for v in p.masterData.current.variants
+      _.extend(master2retailer, matchVariant(v))
+
+  console.log "master2retailer: %j", master2retailer
+  sku2index = {}
+  for es, i in masterStocks
+    rSku = master2retailer[es.sku]
+    continue if not rSku
+    sku2index[rSku] = i
+
+  console.log "s2i: %j", sku2index
+  sku2index
+
+matchVariant = (variant) ->
+  m2r = {}
+  rSku = variant.sku
+  return m2r if not rSku
+  for a in variant.attributes
+    continue if a.name != 'mastersku'
+    mSku = a.value
+    return m2r if not mSku
+    m2r[mSku] = rSku
+    break
+  m2r
+
+stockxmlimport.create = (stock, bar) ->
+  # We don't create new stock entries - only update existing!
+  deferred = Q.defer()
+  bar.tick()
+  deferred.promise
+
+Q.all([retailerChannelInMaster(), retailerProducts(), stocks(rRest), stocks(stockxmlimport.rest)])
+.then ([channelId, retailerProducts, retailerStocks, masterStocks]) ->
+  sku2index = match(masterStocks, retailerProducts)
+
+  posts = []
+  bar = new ProgressBar 'Updating stock [:bar] :percent done', { width: 50, total: retailerStocks.length }
+  for s in retailerStocks
+    s.supplyChannel =
+      typeId: 'channel'
+      id: channelId
+
+    if sku2index[s.sku] >= 0
+      posts.push stockxmlimport.update(s, masterStocks[sku2index[s.sku]], bar)
+    else
+      posts.push stockxmlimport.create(s, bar)
+
+  Q.all(posts).then (v) =>
+    if v.length is 1
+      v = v[0]
+    else
+      v = "#{v.length} Done"
+    console.log v


bug fix

bug fix

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/'


fixes

fixes


bug fix

bug fix


do not show added list if there are no items

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/patleb/admineer.git/'


Intermediate version bump to 1.3.2-pre

Intermediate version bump to 1.3.2-pre

--- coffee-script.coffee
+++ coffee-script.coffee
@@ -21,7 +21,7 @@
   require.registerExtension '.coffee', (content) -> compile content

 # The current CoffeeScript version number.
-exports.VERSION = '1.3.1'
+exports.VERSION = '1.3.2-pre'

 # Words that cannot be used as identifiers in CoffeeScript code
 exports.RESERVED = RESERVED


Sprint.ly authentication, configuration and listing in-progress items

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

--- src/scripts/sprintly.coffee
+++ src/scripts/sprintly.coffee
@@ -0,0 +1,61 @@
+# List stories and other items in Sprint.ly and interact with them.
+#
+# sprintly [product_id] - list in-progress items
+# sprintly token <email:apitoken> - set/update credentials for user (required for other commands to work)
+# sprintly default 1234 - set default product_id
+#
+
+DummyClient = ->
+self = -> this
+for method in ['scope', 'query', 'product']
+  DummyClient::[method] = self
+for method in ['get', 'post', 'put', 'delete']
+  DummyClient::[method] = -> self
+
+module.exports = (robot) ->
+
+  sprintly = (msg, auth) ->
+    if auth ?= robot.brain.data.sprintly?[msg.message.user.id]
+      client = msg.http('https://sprint.ly')
+        .header('accept', 'application/json')
+        .header('authorization', "Basic #{new Buffer(auth).toString('base64')}")
+        .path('/api')
+      client.product = ->
+        if product_id = msg.match[1] ? robot.brain.data.sprintly?.product_id
+          @path("/api/products/#{product_id}")
+        else
+          msg.send "No Product Id has been specified, you can set a default with 'sprintly default 1234'"
+          new DummyClient()
+      client
+    else
+      msg.send "API token not found, set it with 'sprintly token <email:apitoken>'"
+      new DummyClient()
+
+  robot.respond /sprintly +token +(.*)/i, (msg) ->
+    sprintly(msg, msg.match[1])
+      .scope('products.json')
+      .get() (err, res, body) ->
+        if res.statusCode < 400
+          robot.brain.data.sprintly ?= {}
+          robot.brain.data.sprintly[msg.message.user.id] = msg.match[1]
+          msg.send "API token set"
+        else
+          msg.send "Unable to verify API token: #{body}"
+
+  robot.respond /sprintly +default +(\d+) *$/, (msg) ->
+    robot.brain.data.sprintly ?= {}
+    robot.brain.data.sprintly.product_id = msg.match[1]
+    msg.send "Default Product ID set to #{msg.match[1]}"
+
+  robot.respond /sprintly *( +\d+)? *$/, (msg) ->
+    sprintly(msg).product()
+      .scope('items.json')
+      .query(status: 'in-progress')
+      .get() (err, res, body) ->
+        if res.statusCode == 200
+          payload = JSON.parse(body)
+          items = payload.map (item) ->
+            "##{item.number} #{item.score} #{if item.type isnt 'story' then "#{item.type}: " else ""}#{item.title} https://sprint.ly/#!/product/#{item.product.id}/item/#{item.number}"
+          msg.send items.join("\n")
+        else
+          msg.send "Something came up: #{body}"


request repo scope

request repo scope

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/conduktor/web.git/'


Cleanup imports.

Cleanup imports.

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/commercetools/graphite-feeder.git/'


fix: GoodData typo

fix: GoodData typo

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-wrapper.git/'


Add button on hover for addComponentsTreema

--- app/views/editor/component/ThangComponentEditView.coffee
+++ app/views/editor/component/ThangComponentEditView.coffee
@@ -247,7 +247,15 @@

 class ComponentNode extends TreemaObjectNode
   valueClass: 'treema-component'
+  addButtonTemplate: ''
   collection: false
+
+  build: ->
+    super()
+    @$el.find('> .treema-row').append @addButtonTemplate
+    @$el.find('.add-button').click =>
+      @callbacks.enter?(@)
+    @$el

   buildValueForDisplay: (valEl) ->
     s = @data.system + '.' + @data.name
@@ -256,3 +264,11 @@
   onEnterPressed: (args...) ->
     super(args...)
     @callbacks.enter?(@)
+
+  onMouseEnter: (e) ->
+    @$el.find('.add-button').show()
+    super()
+
+  onMouseLeave: (e) ->
+    @$el.find('.add-button').hide()
+    super()


Sort installed packages by name

Sort installed packages by name

--- src/app/installed-packages-config-panel.coffee
+++ src/app/installed-packages-config-panel.coffee
@@ -1,3 +1,4 @@
+_ = require 'underscore'
 ConfigPanel = require 'config-panel'
 PackageConfigView = require 'package-config-view'

@@ -9,5 +10,5 @@
     @div class: 'installed-packages'

   initialize: ->
-    for pack in atom.getLoadedPackages()
+    for pack in _.sortBy(atom.getLoadedPackages(), 'name')
       @append(new PackageConfigView(pack.metadata))


docs (API) Fix broken link.

docs (API) Fix broken link.

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/'


ComputeController: add missing curly braces.

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -90,9 +90,10 @@

   methodNotSupportedBy = (machine)->
     if machine?.provider is 'managed'
-      return
+      return {
         name    : 'NotSupported'
         message : 'Operation is not supported for this VM'
+      }

   errorHandler: (call, task, machine)->


UserEnvironmentDataProvider: Added missing uid check.

--- client/app/lib/userenvironmentdataprovider.coffee
+++ client/app/lib/userenvironmentdataprovider.coffee
@@ -190,7 +190,7 @@

     return null  unless IDE

-    for i in IDE.instances when i.mountedMachineUId
+    for i in IDE.instances when i.mountedMachineUId is uid
       instance = i
       break


Manage static methods on classes

Manage static methods on classes

--- lib/php-class-provider.coffee
+++ lib/php-class-provider.coffee
@@ -26,28 +26,38 @@
     return suggestions

   confirm: (suggestion) ->
-    snippetModule = atom.packages.getActivePackage('snippets').mainModule
-
-    body = "("
-    for arg, index in suggestion.data.args
-      body += "," if body != "("
-      body += "${" + (index+1) + ":" + arg + "}"
-    body += ")$0"
-
-    snippetName = suggestion.word + suggestion.label
-    snippet =
-      ".source.php":
-        snippetName:
-          prefix: suggestion.prefix
-          body: suggestion.word + body
-    snippetModule.add('current', snippet)
-
     selection = @editor.getSelection()
     startPosition = selection.getBufferRange().start
     buffer = @editor.getBuffer()

-    # Emit the snippet
-    snippetModule.expandSnippetsUnderCursors(@editor)
+    # if some args (even empty) => instanciation
+    if suggestion.data?.args?
+      snippetModule = atom.packages.getActivePackage('snippets').mainModule
+
+      body = "("
+      for arg, index in suggestion.data.args
+        body += "," if body != "("
+        body += "${" + (index+1) + ":" + arg + "}"
+      body += ")$0"
+
+      snippetName = suggestion.word + suggestion.label
+      snippet =
+        ".source.php":
+          snippetName:
+            prefix: suggestion.prefix
+            body: suggestion.word + body
+      snippetModule.add('current', snippet)
+
+      # Emit the snippet
+      snippetModule.expandSnippetsUnderCursors(@editor)
+      snippetModule.deactivate()
+      snippetModule.activate()
+
+    # Static methods on classes
+    else
+      cursorPosition = @editor.getCursorBufferPosition()
+      buffer.delete Range.fromPointWithDelta(cursorPosition, 0, -suggestion.prefix.length)
+      @editor.insertText suggestion.word + "::"

     return false # Don't fall back to the default behavior


test findId

test findId

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

--- test/lib/test-findId.coffee
+++ test/lib/test-findId.coffee
@@ -0,0 +1,98 @@
+assert = require 'assert'
+findId = require '../../lib/find-id'
+
+describe 'test findId', ->
+
+  describe 'with id', ->
+
+    it 'should return the id', ->
+
+      id = 'test'
+      result = findId id:id
+      assert.equal result, id
+
+  describe 'without id', ->
+
+    id = 'test'
+
+    describe 'with npm config prop', ->
+
+      before 'add npm config prop', -> process.env.npm_package_config_nucid = 'test'
+
+      after 'remove npm config prop', -> delete process.env.npm_package_config_nucid
+
+      it 'should find it', ->
+
+        options = {}
+        result = findId options
+
+        assert.equal result, id
+        assert.equal options.id, id
+
+
+    describe 'with env prop', ->
+
+      before 'add env prop', -> process.env.NUCID = 'test'
+
+      after 'remove env prop', -> delete process.env.NUCID
+
+      it 'should find it', ->
+
+        options = {}
+        result = findId options
+
+        assert.equal result, id
+        assert.equal options.id, id
+
+
+    describe 'with cli arg', ->
+
+      before 'add cli arg', -> process.argv.push '--nucid=test'
+
+      after 'remove cli arg', -> process.argv.pop()
+
+      it 'should find it', ->
+
+        options = {}
+        result = findId options
+
+        assert.equal result, id
+        assert.equal options.id, id
+
+
+    describe 'with .nuc.name in CWD', ->
+
+      cwd = process.cwd()
+
+      before 'move to test dir with .nuc.name file', ->
+
+        process.chdir require('path').resolve 'test', 'helpers'
+
+      after 'return to original cwd', -> process.chdir cwd
+
+      it 'should find it', ->
+
+        options = {}
+        result = findId options
+
+        assert.equal result, id
+        assert.equal options.id, id
+
+
+    describe 'with noFindID', ->
+
+      it 'should return nothing', ->
+
+        options = noFindId:true
+        result = findId options
+
+        assert.equal result, undefined
+
+
+    describe 'without id anywhere', ->
+
+      it 'should return error', ->
+
+        result = findId()
+
+        assert.equal result?.__error, '`id` required for nuc'


test entry

test entry

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

--- test/index.coffee
+++ test/index.coffee
@@ -0,0 +1,13 @@
+Keyconfig = require '../lib'
+
+describe 'Keyconfig', ->
+
+  it 'should proxy underscore methods', ->
+
+    fixture = require './proxy-underscore.json'
+
+    bar = new Keyconfig fixture.collections
+    baz = bar.filter name: 'y'
+
+    baz.should.have.lengthOf 1
+    baz[0].name.should.eql 'y'


script for sending announcements to all rooms

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

--- src/scripts/announce.coffee
+++ src/scripts/announce.coffee
@@ -0,0 +1,60 @@
+# Description:
+#   Send messages to all chat rooms.
+#
+# Dependencies:
+#   None
+#
+# Configuration:
+#   HUBOT_ANNOUNCE_ROOMS - comma-separated list of rooms
+#
+# Commands:
+#   hubot announce "<message>" - Sends a message to all hubot rooms.
+#   hubot announce downtime for "<service>" starting <timeframe> - Syntactic sugar for announcing downtime commencement
+#   hubot announce downtime complete for "<service>" - Syntactic sugar for announcing downtime completion
+#
+# Author:
+#   Morgan Delagrange
+#
+# URLS:
+#   /broadcast/create - Send a message to designated, comma-separated rooms.
+
+module.exports = (robot) ->
+
+  if process.env.HUBOT_ANNOUNCE_ROOMS
+    allRooms = process.env.HUBOT_ANNOUNCE_ROOMS.split(',')
+  else
+    allRooms = []
+
+  robot.respond /announce "(.*)"/i, (msg) ->
+    announcement = msg.match[1]
+    for room in allRooms
+      robot.messageRoom room, announcement
+
+  robot.respond /announce downtime for "(.*)" starting (.*)/i, (msg) ->
+    user = msg.message.user
+    service = msg.match[1]
+    startTime = msg.match[2]
+
+    message = ["The '#{service}' service will be going down for maintenance starting #{startTime}.",
+      "If you have questions about this maintenance, please talk to #{user.name} in the the #{user.room} room.  Thank you for your patience."]
+
+    for room in allRooms
+      robot.messageRoom room, message...
+    msg.reply "Don't forget to pause monitoring for this service."
+
+  robot.respond /announce downtime complete for "(.*)"/i, (msg) ->
+    service = msg.match[1]
+    for room in allRooms
+      robot.messageRoom room,
+          "Maintenance for the '#{service}' service is complete."
+    msg.reply "Don't forget to resume monitoring for this service."
+
+  robot.router.post "/broadcast/create", (req, res) ->
+    if req.body.rooms
+      rooms = req.body.rooms.split(',')
+    else
+      rooms = allRooms
+
+    for room in rooms
+      robot.messageRoom room, req.body.message
+    res.end "Message Sent"


Send response before saving to database

Send response before saving to database

--- server_setup.coffee
+++ server_setup.coffee
@@ -95,10 +95,9 @@
 setupFallbackRouteToIndex = (app) ->
   app.all '*', (req, res) ->
     if req.user
+      sendMain(req, res)
       req.user.set('lastIP', req.connection.remoteAddress)
-      req.user.save (err) =>
-        # ignore save error
-        sendMain(req, res)
+      req.user.save
     else
       user = auth.makeNewUser(req)
       makeNext = (req, res) -> -> sendMain(req, res)


temp debugging

temp debugging


Move path stuff under is*

Move path stuff under is*

--- src/directory.coffee
+++ src/directory.coffee
@@ -77,16 +77,6 @@
   Section: Directory Metadata
   ###

-  # Public: Returns the {String} basename of the directory.
-  getBaseName: ->
-    path.basename(@path)
-
-  # Public: Returns the directory's {String} path.
-  #
-  # This may include unfollowed symlinks or relative directory entries. Or it
-  # may be fully resolved, it depends on what you give it.
-  getPath: -> @path
-
   # Public: Returns a {Boolean}, always false.
   isFile: -> false

@@ -97,6 +87,16 @@
   # of the filesystem, or false if it isn't.
   isRoot: ->
     @getParent().getRealPathSync() is @getRealPathSync()
+
+  # Public: Returns the directory's {String} path.
+  #
+  # This may include unfollowed symlinks or relative directory entries. Or it
+  # may be fully resolved, it depends on what you give it.
+  getPath: -> @path
+
+  # Public: Returns the {String} basename of the directory.
+  getBaseName: ->
+    path.basename(@path)

   # Public: Traverse within this Directory to a child File. This method doesn't
   # actually check to see if the File exists, it just creates the File object.