Add metabadge check to badge cron

Add metabadge check to badge cron

--- src/clj/salava/badge/cron.clj
+++ src/clj/salava/badge/cron.clj
@@ -8,37 +8,37 @@
             [clojure.data.json :as json]))

 #_(defn- assertion [assertion-url]
-  (http/http-req {:socket-timeout 10000
-                  :conn-timeout   10000
-                  :method :get
-                  :url assertion-url
-                  :throw-exceptions false
-                  :as :json
-                  :accept :json}))
+   (http/http-req {:socket-timeout 10000
+                   :conn-timeout   10000
+                   :method :get
+                   :url assertion-url
+                   :throw-exceptions false
+                   :as :json
+                   :accept :json}))

 (defn- assertion [asr-url]
  (let [response (->> (http/http-req {:socket-timeout 10000
-                           :conn-timeout 10000
-                           :method :get
-                           :url asr-url
-                           :throw-exceptions false
-                           :accept :json})
+                                     :conn-timeout 10000
+                                     :method :get
+                                     :url asr-url
+                                     :throw-exceptions false
+                                     :accept :json})
                      (clojure.walk/keywordize-keys))]
    (if (clojure.string/includes? (get-in response [:headers :Content-Type]) "application/json")
-        (assoc response :body (json/read-str (:body response) :key-fn keyword))
-        nil)))
+       (assoc response :body (json/read-str (:body response) :key-fn keyword))
+       nil)))

 (defn- revoked? [asr]
   (or (= (:status asr) 410) (get-in asr [:body :revoked])))

 #_(defn- remote-url [factory-url asr]
-  (when (and (string? factory-url) (map? asr))
-    (cond
-      (string/starts-with? (get asr :id "") factory-url) factory-url
-      (string/starts-with? (get-in asr [:verify :url] "") factory-url) factory-url
-      (and (= (get-in asr [:related :type]) "Assertion")
-           (string/starts-with? (get (http/json-get (get-in asr [:related :id])) :id "") factory-url)) factory-url
-      :else nil)))
+   (when (and (string? factory-url) (map? asr))
+     (cond
+       (string/starts-with? (get asr :id "") factory-url) factory-url
+       (string/starts-with? (get-in asr [:verify :url] "") factory-url) factory-url
+       (and (= (get-in asr [:related :type]) "Assertion")
+            (string/starts-with? (get (http/json-get (get-in asr [:related :id])) :id "") factory-url)) factory-url
+       :else nil)))

 (defn- remote-url [factory-url asr]
  (when (and (string? factory-url) (not (clojure.string/blank? factory-url)) (map? asr))
@@ -56,15 +56,15 @@
            :else nil)))))

 #_(defn- issuer-verified? [factory-url asr]
-  (when (and (string? factory-url) (map? asr) (string/starts-with? (get asr :id "") factory-url))
-    (try
-      (let [badge (if (map? (:badge asr)) (:badge asr) (http/json-get (:badge asr)))
-            issuer-url (if (map? (:issuer badge)) (get-in badge [:issuer :id]) (:issuer badge))
-            issuer-id (last (re-find #"/v1/client.*[?&]key=(\w+)" issuer-url))]
-        (if issuer-id
-          (:verified (http/json-get (str factory-url "/v1/client?key=" issuer-id)))
-          false))
-      (catch Throwable _ false))))
+   (when (and (string? factory-url) (map? asr) (string/starts-with? (get asr :id "") factory-url))
+     (try
+       (let [badge (if (map? (:badge asr)) (:badge asr) (http/json-get (:badge asr)))
+             issuer-url (if (map? (:issuer badge)) (get-in badge [:issuer :id]) (:issuer badge))
+             issuer-id (last (re-find #"/v1/client.*[?&]key=(\w+)" issuer-url))]
+         (if issuer-id
+           (:verified (http/json-get (str factory-url "/v1/client?key=" issuer-id)))
+           false))
+       (catch Throwable _ false))))

 (defn- issuer-verified? [factory-url asr]
  (let [factory-url (remote-url factory-url asr)]
@@ -79,7 +79,6 @@

 (defn- check-badge [ctx db-conn factory-url user-badge]
   (let [asr (assertion (:assertion_url user-badge))
-        related-asr (->> (get-in asr [:body :related]) first :id)
         factory-url (remote-url factory-url (:body asr))
         delete-user-metabadge (first (u/plugin-fun (u/get-plugins ctx) "db" "clear-user-metabadge!"))
         check-metabadge (first (u/plugin-fun (u/get-plugins ctx) "db" "metabadge?!"))]
@@ -115,7 +114,7 @@
             ;(log/debug "check-badges: working on id " (:id user-badge))
             (check-badge ctx db-conn factory-url user-badge)
             (jdbc/execute! db-conn ["UPDATE user_badge SET last_checked = UNIX_TIMESTAMP() WHERE id = ?"
-                              (:id user-badge)])
+                                    (:id user-badge)])
             (Thread/sleep 100)
             (catch InterruptedException _)
             (catch Throwable ex


experimental support for inlining closure js into :none modules

this potentially saves a lot of requests

--- src/clj/shadow/cljs/build.clj
+++ src/clj/shadow/cljs/build.clj
@@ -2167,8 +2167,96 @@
        (or (not (.exists x))
            (.isDirectory x))))

+;; FIXME: this could inline everything from a jar since they will never be live-reloaded
+;; but it would need to create a proper source-map for the module file
+;; since we need that for CLJS files
+;; compact-mode has a bunch of work for index source-maps, should be an easy port
+(defn inlineable? [{:keys [type from-jar provides requires] :as src}]
+  ;; only inline things from jars
+  (and from-jar
+       ;; only js is inlineable since we want proper source maps for cljs
+       (= :js type)
+       ;; only inline goog for now
+       (every? #(str/starts-with? (str %) "goog.") requires)
+       (every? #(str/starts-with? (str %) "goog.") provides)
+       ))
+
+(defn flush-unoptmized-module!
+  [{:keys [dev-inline-js public-dir public-path unoptimizable] :as state}
+   {:keys [default js-name name prepend prepend-js append-js sources web-worker] :as mod}]
+  (let [inlineable-sources
+        (if-not dev-inline-js
+          []
+          (->> sources
+               (map #(get-in state [:sources %]))
+               (filter inlineable?)
+               (into [])))
+
+        inlineable-set
+        (into #{} (map :name) inlineable-sources)
+
+        target
+        (io/file public-dir js-name)
+
+        inlined-js
+        (->> inlineable-sources
+             (map :output)
+             (str/join "\n"))
+
+        inlined-provides
+        (->> inlineable-sources
+             (mapcat :provides)
+             (into #{}))
+
+        ;; goog.writeScript_ (via goog.require) will set these
+        ;; since we skip these any later goog.require (that is not under our control, ie REPL)
+        ;; won't recognize them as loaded and load again
+        closure-require-hack
+        (->> inlineable-sources
+             (map :js-name)
+             (map (fn [js]
+                    ;; not entirely sure why we are setting the full path and just the name
+                    ;; goog seems to do that
+                    (str "goog.dependencies_.written[\"" js "\"] = true;\n"
+                         "goog.dependencies_.written[\"" public-path "/" js "\"] = true;")
+                    ))
+             (str/join "\n"))
+
+        requires
+        (->> sources
+             (remove inlineable-set)
+             (mapcat #(get-in state [:sources % :provides]))
+             (distinct)
+             (remove inlined-provides)
+             (map (fn [ns]
+                    (str "goog.require('" (comp/munge ns) "');")))
+             (str/join "\n"))
+
+        out
+        (str prepend prepend-js inlined-js closure-require-hack requires append-js)
+
+        out
+        (if (or default web-worker)
+          ;; default mod needs closure related setup and goog.addDependency stuff
+          (str unoptimizable
+               "var SHADOW_MODULES = {};\n"
+               (when web-worker
+                 "\nvar CLOSURE_IMPORT_SCRIPT = function(src) { importScripts(src); };\n")
+               (closure-defines-and-base state)
+               (closure-goog-deps state)
+               "\n\n"
+               out)
+          ;; else
+          out)
+
+        out
+        (str out "\n\nSHADOW_MODULES[" (pr-str (str name)) "] = true;\n")]
+
+    (spit target out)))
+
+
 (defn flush-unoptimized!
-  [{:keys [build-modules public-dir unoptimizable] :as state}]
+  [{:keys [build-modules public-dir] :as state}]
   {:pre [(directory? public-dir)]}

   (when-not (seq build-modules)
@@ -2181,33 +2269,8 @@

     (flush-manifest public-dir build-modules)

-    ;; flush fake modules
-    (doseq [{:keys [default js-name name prepend prepend-js append-js sources web-worker] :as mod} build-modules]
-      (let [provided-ns (mapcat #(reverse (get-in state [:sources % :provides]))
-                          sources)
-            target (io/file public-dir js-name)
-
-            out (->> provided-ns
-                     (map (fn [ns]
-                            (str "goog.require('" (comp/munge ns) "');")))
-                     (str/join "\n"))
-            out (str prepend prepend-js out append-js)
-            out (if (or default web-worker)
-                  ;; default mod needs closure related setup and goog.addDependency stuff
-                  (str unoptimizable
-                       "var SHADOW_MODULES = {};\n"
-                       (when web-worker
-                         "\nvar CLOSURE_IMPORT_SCRIPT = function(src) { importScripts(src); };\n")
-                       (closure-defines-and-base state)
-                       (closure-goog-deps state)
-                       "\n\n"
-                       out)
-                  ;; else
-                  out)
-
-            out (str out "\n\nSHADOW_MODULES[" (pr-str (str name)) "] = true;\n")]
-
-        (spit target out)))
+    (doseq [mod build-modules]
+      (flush-unoptmized-module! state mod))

     state
     ))
@@ -2223,7 +2286,10 @@
     (count (line-seq rdr))))

 (defn create-index-map
-  [{:keys [public-dir cljs-runtime-path] :as state} out-file init-offset {:keys [sources js-name] :as mod}]
+  [{:keys [public-dir cljs-runtime-path] :as state}
+   out-file
+   init-offset
+   {:keys [sources js-name] :as mod}]
   (let [index-map
         (reduce
           (fn [src-map src-name]
@@ -2599,6 +2665,7 @@
        :use-file-min true

        :bundle-foreign :inline
+       :dev-inline-js true

        :static-fns true
        :elide-asserts false


disable closure type checks by default, too many invalid warnings

--- src/clj/shadow/cljs/build.clj
+++ src/clj/shadow/cljs/build.clj
@@ -2700,6 +2700,9 @@

        ::cc (make-closure-compiler)

+       :closure-warnings
+       {:check-types :off}
+
        :runtime {:print-fn :console}
        :macros-loaded #{}
        :use-file-min true


WIP on pagination

WIP on pagination

--- src/cljs/cglossa/results.cljs
+++ src/cljs/cglossa/results.cljs
@@ -24,7 +24,7 @@
                        :bs-size  "small"
                        :disabled (or @searching?
                                      (zero? @total))
-                       :style {:margin-bottom 10}}
+                       :style    {:margin-bottom 10}}
      [b/menuitem {:event-key :position, :on-select on-select}
       (when (= sort-by :position) [b/glyphicon {:glyph "ok"}]) "  By corpus position"]
      [b/menuitem {:event-key :match, :on-select on-select}
@@ -42,40 +42,53 @@
      [b/menuitem {:event-key :lemma, :on-select on-select} "Lemmas"]
      [b/menuitem {:event-key :pos, :on-select on-select} "Parts-of-speech"]]))

-(defn- pagination [{{total :total} :results-view}]
-  (when (> @total page-size)
-    [:div.pull-right
-     [:nav
-      [:ul.pagination.pagination-sm
-       [:li
-        [:a
-         {:href "#", :aria-label "First"}
-         [:span {:aria-hidden "true"} "«"]]]
-       [:li
-        [:a
-         {:href "#", :aria-label "Previous"}
-         [:span {:aria-hidden "true"} "‹"]]]
-       [:li
-        [:select.form-control.input-sm {:style {:direction        "rtl"
-                                                :width            60
-                                                :float            "left"
-                                                :border-radius    0
-                                                :height           27
-                                                :line-height      27
-                                                :border           0
-                                                :outline          "1px solid #ddd"
-                                                :margin-top       1
-                                                :background-color "white"}}
-         (for [i (range 1 101)]
-           ^{:key i} [:option {:value i} i])]]
-       [:li
-        [:a
-         {:href "#", :aria-label "Next"}
-         [:span {:aria-hidden "true"} "›"]]]
-       [:li
-        [:a
-         {:href "#", :aria-label "Last"}
-         [:span {:aria-hidden "true"} "»"]]]]]]))
+(defn- pagination [{{:keys [total page-no]} :results-view}]
+  (let [set-page (fn [n]
+                   (let [n* (js/parseInt n)]
+                     (reset! page-no n*)))]
+    (when (> @total page-size)
+      [:div.pull-right
+       [:nav
+        [:ul.pagination.pagination-sm
+         [:li
+          [:a {:href       "#"
+               :aria-label "First"
+               :title      "First"
+               :on-click   #(set-page 1)}
+           [:span {:aria-hidden "true"} "«"]]]
+         [:li
+          [:a {:href       "#"
+               :aria-label "Previous"
+               :title      "Previous"
+               :on-click   #(set-page (dec @page-no))}
+           [:span {:aria-hidden "true"} "‹"]]]
+         [:li
+          [:select.form-control.input-sm {:style     {:direction        "rtl"
+                                                      :width            60
+                                                      :float            "left"
+                                                      :border-radius    0
+                                                      :height           27
+                                                      :line-height      27
+                                                      :border           0
+                                                      :outline          "1px solid #ddd"
+                                                      :margin-top       1
+                                                      :background-color "white"}
+                                          :value     @page-no
+                                          :on-change #(set-page (.-target.value %))}
+           (for [i (range 1 101)]
+             ^{:key i} [:option {:value i} i])]]
+         [:li
+          [:a {:href       "#"
+               :aria-label "Next"
+               :title      "Next"
+               :on-click   #(set-page (inc @page-no))}
+           [:span {:aria-hidden "true"} "›"]]]
+         [:li
+          [:a {:href       "#"
+               :aria-label "Last"
+               :title      "Last"
+               :on-click   #(set-page (inc (quot @total page-size)))}
+           [:span {:aria-hidden "true"} "»"]]]]]])))

 (defn- concordance-toolbar [{{page-no :page-no} :results-view :as a} m]
   [:div.row {:style {:margin-top 15}}


Fix bug not showing first event in events

--- src/cljs/my_money/events.cljs
+++ src/cljs/my_money/events.cljs
@@ -59,7 +59,7 @@
       [:th "Date"]
       [:th "Amount"]
       [:th "Recipient"]]]
-    [:tbody (for [event (rest events)]
+    [:tbody (for [event events]
               ^{:key (:id event)}
               [:tr
                [:td (str (:transaction_date event))]


Move change code into a helper

Move change code into a helper

--- src/cljs/retroboard/user.cljs
+++ src/cljs/retroboard/user.cljs
@@ -58,13 +58,16 @@
        :url "/boards"
        :chan ch})))

-(defn input [owner id placeholder & type]
-  (dom/input #js {:type (or (first type) "text")
+(defn input [id placeholder on-change & [type]]
+  (dom/input #js {:type (or type "text")
                   :id (name id)
-                  :onChange (fn [e]
-                              (om/set-state! owner id
-                                             (.. e -target -value)))
+                  :onChange on-change
                   :placeholder placeholder}))
+
+(defn handle-change [owner id]
+  (fn [e]
+    (let [new-value (.. e -target -value)]
+      (om/set-state! owner id new-value))))

 (defn login-view [app owner {:keys [on-login]}]
   (reify
@@ -84,8 +87,11 @@
       (dom/div #js {:id "login-signup"}
                (dom/form #js {:id "login"
                               :style (display (= screen :login))}
-                         (input owner :email "Your username or email")
-                         (input owner :password "Your password" "password")
+                         (input :email "Your username or email"
+                                (handle-change owner :email))
+                         (input :password "Your password"
+                                (handle-change owner :password)
+                                "password")
                          (dom/button
                           #js {:onClick (fn [e]
                                           (.preventDefault e)
@@ -98,9 +104,13 @@
                                 "or sign up"))
                (dom/form #js {:id "signup"
                               :style (display (= screen :signup))}
-                         (input owner :username "Choose a username")
-                         (input owner :email "Your email")
-                         (input owner :password "Choose a password" "password")
+                         (input :username "Choose a username"
+                                (handle-change owner :username))
+                         (input :email "Your email"
+                                (handle-change owner :email))
+                         (input :password "Choose a password"
+                                (handle-change owner :password)
+                                "password")
                          (dom/button
                           #js {:onClick (fn [e]
                                           (.preventDefault e)


Store Ruby-defined methods directly on the object

--- src/clojure_ruby/evaluate.clj
+++ src/clojure_ruby/evaluate.clj
@@ -5,9 +5,14 @@
 (defn evaluate-body [system body]
   (mapv (partial evaluate system) body))

+(defn method-lookup [obj method-name]
+  (get-in obj [:methods method-name]))
+
 (defn ruby-msg [system obj method-name args]
-  (if-let [meth (get-in obj [:methods method-name])]
-    (apply meth system obj args)
+  (if-let [meth (method-lookup obj method-name)]
+    (if (fn? meth)
+      (apply meth system obj args)
+      (evaluate-body system meth))
     (throw (ex-info "Method lookup failed" {:object obj, :method method-name}))))

 (defmulti evaluate-one (fn [vars stmt] (first stmt)))
@@ -21,9 +26,10 @@
   (let [[_ name] stmt]
     (if-let [var (get @(:variables system) name)]
       var
-      (if-let [meth (get @(:methods system) name)]
-        (evaluate-body system meth)
-        (throw (ex-info "Cannot find variable or method" {:name name}))))))
+      (let [self (get @(:variables system) "self")]
+        (if (method-lookup self name)
+          (ruby-msg system self name [])
+          (throw (ex-info "Cannot find variable or method" {:name name})))))))

 (defmethod evaluate-one :method-call [system stmt]
   (let [[_ obj method & args] stmt
@@ -77,7 +83,7 @@

 (defmethod evaluate-one :method-def [system stmt]
   (let [[_ name args & body] stmt]
-    (swap! (:methods system) assoc name body)))
+    (swap! (:variables system) assoc-in ["self" :methods name] body)))

 (defn evaluate [system stmt]
   (try
@@ -87,7 +93,6 @@

 (defn evaluate-all [create-string create-number as-host-boolean initial-variables stmts]
   (let [system {:variables (atom initial-variables)
-                :methods (atom {})
                 :create-string create-string
                 :create-number create-number
                 :as-host-boolean as-host-boolean}]


Bug fixed

Bug fixed

--- src/blocks_editor/core.cljs
+++ src/blocks_editor/core.cljs
@@ -35,8 +35,8 @@
   [settings]
   (reagent/render
    [v/ui]
-   (js/$ "app"))
+   (-> "#app" js/$ (aget 0)))
   (doto (.ajax js/$ (clj->js  {:url "assets/xml/toolbox.xml"}))
-    (.done #(b/inject (js/$ "#blocklyDiv")
+    (.done #(b/inject (-> "#blocklyDiv" js/$ (aget 0))
                       (clj->js {:toolbox %})))))


Prep work to allow more storage state.

Prep work to allow more storage state.

--- src/cbfg/world-storage.cljs
+++ src/cbfg/world-storage.cljs
@@ -6,44 +6,49 @@
                               get-el-innerHTML set-el-innerHTML]]
             [cbfg.fence :refer [make-fenced-pump]]))

-(defn storage-get [actx opaque-id key]
-  (ago storage-get actx
-       {:opaque-id opaque-id :status :ok :key key :val "yay"}))
-
-(defn storage-set [actx opaque-id key val]
-  (ago storage-set actx
-       {:opaque-id opaque-id :status :ok}))
-
-(defn storage-del [actx opaque-id key]
-  (ago storage-del actx
-       {:opaque-id opaque-id :status :ok}))
-
-(defn storage-scan [actx opaque-id from to]
-  (ago storage-del actx
-       {:opaque-id opaque-id :status :ok}))
-
-(defn storage-noop [actx opaque-id]
-  (ago storage-del actx
-       {:opaque-id opaque-id :status :ok}))
-
-(def storage-cmd-handlers
+(defn make-storage-cmd-handlers [kvs changes last-seq max-deleted-seq]
   {"get"  [["key"]
-           (fn [c] {:rq #(storage-get % (:opaque-id c) (:key c))})]
+           (fn [c] {:rq
+                    (fn [actx]
+                      (ago storage-get actx
+                           {:opaque-id (:opaque-id c) :status :ok
+                            :key (:key c) :val "yay"}))})]
    "set"  [["key" "val"]
-           (fn [c] {:rq #(storage-set % (:opaque-id c) (:key c) (:val c))})]
+           (fn [c] {:rq
+                    (fn [actx]
+                      (ago storage-get actx
+                           {:opaque-id (:opaque-id c) :status :ok
+                            :key (:key c)}))})]
    "del"  [["key"]
-           (fn [c] {:rq #(storage-del % (:opaque-id c) (:key c))})]
+           (fn [c] {:rq
+                    (fn [actx]
+                      (ago storage-get actx
+                           {:opaque-id (:opaque-id c) :status :ok
+                            :key (:key c)}))})]
    "scan" [["from" "to"]
-           (fn [c] {:rq #(storage-scan % (:opaque-id c) (:from c) (:to c))})]
+           (fn [c] {:rq
+                    (fn [actx]
+                      (ago storage-get actx
+                           {:opaque-id (:opaque-id c) :status :ok
+                            :from (:from c) :to (:to c)}))})]
    "noop" [[]
-           (fn [c] {:rq #(storage-noop % (:opaque-id c))})]
+           (fn [c] {:rq
+                    (fn [actx]
+                      (ago storage-get actx
+                           {:opaque-id (:opaque-id c) :status :ok}))})]
    "test" [[]
-           (fn [c] {:rq #(cbfg.fence/test %)})]})
+           (fn [c] {:rq #(cbfg.fence/test % (:opaque-id c))})]})

 (def storage-max-inflight (atom 10))

 (defn world-vis-init [el-prefix]
-  (let [cmd-ch (map< (fn [ev] {:op (.-id (.-target ev))})
+  (let [kvs (atom {})
+        changes (atom {})
+        last-seq (atom 0)
+        max-deleted-seq (atom 0)
+        storage-cmd-handlers (make-storage-cmd-handlers kvs changes
+                                                        last-seq max-deleted-seq)
+        cmd-ch (map< (fn [ev] {:op (.-id (.-target ev))})
                      (merge (map #(listen-el (gdom/getElement %) "click")
                                  (keys storage-cmd-handlers))))]
     (vis-init (fn [world]


start should fail if only started

start should fail if only started

--- src/celestial/workflows.clj
+++ src/celestial/workflows.clj
@@ -90,6 +90,7 @@
   "Start a vm instance"
   [{:keys [machine] :as spec}]
   (let [vm (vconstruct spec)]
+    (assert (not (= (.status vm) "running"))) ; might not match all providers
     (info "starting" machine)
     (.start vm)
     (assert (= (.status vm) "running")) ; might not match all providers


Bugfix: rewrite-fn could return a non-fn AST

--- src/oxcart/passes/fn_reduction.clj
+++ src/oxcart/passes/fn_reduction.clj
@@ -113,7 +113,7 @@
    munged-fns-atom]
   (if (not (or (pattern/fn? fn-ast)
                (fn-is-multiple-arity? fn-ast)))
-    ast
+    fn-ast
     (let [[def-ast methods env]
           (if-let [fn-name (-> fn-ast :local :name)]
             ;; everything goes to shit and we need to do extra bindings work


break out indexed-sources helper, will need to reuse

--- src/clj/cljs/source_map.clj
+++ src/clj/cljs/source_map.clj
@@ -5,10 +5,13 @@
             [clojure.pprint :as pp]
             [cljs.source-map.base64-vlq :as base64-vlq]))

+(defn indexed-sources [sources]
+  (->> sources
+    (map-indexed (fn [a b] [a b]))
+    (reduce (fn [m [i v]] (assoc m v i)) {})))
+
 (defn source-compare [sources]
-  (let [sources (->> sources
-                  (map-indexed (fn [a b] [a b]))
-                  (reduce (fn [m [i v]] (assoc m v i)) {}))]
+  (let [sources (indexed-sources sources)]
     (fn [a b] (compare (sources a) (sources b)))))

 (defn seg->map [seg source-map]


fix: disable `:escape-slash` option for json writes

to match previous behavior

--- src/clj/datasplash/core.clj
+++ src/clj/datasplash/core.clj
@@ -39,7 +39,7 @@

 (def required-ns (atom #{}))

-(def fast-charred-write (charred/write-json-fn {:indent-str nil}))
+(def fast-charred-write (charred/write-json-fn {:indent-str nil :escape-slash false}))

 (defn write-json-str [data]
   (let [w (StringWriter.)]


Add dev-restart function for REPL development

--- src/clj/train_race/core.clj
+++ src/clj/train_race/core.clj
@@ -46,6 +46,15 @@
     (log/info component "started"))
   (.addShutdownHook (Runtime/getRuntime) (Thread. stop-app)))

+(defn dev-restart
+  ([] (dev-restart nil))
+  ([& args]
+   (log/info "Shutting down all services")
+   (doseq [component (:stopped (mount/stop))]
+     (log/info component "stopped"))
+   (log/info "Restarting..")
+   (start-app args)))
+
 (defn -main [& args]
   (cond
     (some #{"migrate" "rollback"} args)


removed debug logging

removed debug logging

--- src/cljs/redditv/utils.cljs
+++ src/cljs/redditv/utils.cljs
@@ -91,8 +91,7 @@
 (defn decode-html-string [s]
   (let [parser (js/DOMParser.)
         html-string (str "<!doctype html><body>" s)
-        decoded-string (.parseFromString parser html-string "text/html")
-        _ (.log js/console decoded-string)]
+        decoded-string (.parseFromString parser html-string "text/html")]
     (aget decoded-string "body" "textContent")))

 #_(decode-html-string test-uri)


Updated ui layout for fixed toolbar

Updated ui layout for fixed toolbar

--- src/css-guide/guideui/ui.cljs
+++ src/css-guide/guideui/ui.cljs
@@ -228,22 +228,25 @@
     (let [{:keys [parts/selected-part parts searchbar] :or {parts/selected-part 0}} (om/props this)
           part-names (map :part/title parts)]
       (dom/div nil
-        (dom/div #js {:className "o-toolbar o-toolbar--framed u-row--collapse u-trailer--half"}
-          (dom/div #js {:className "u-column--4 u-column--3@md u-column--2@lg u-middle"}
-            (dom/div #js {:className "o-toolbar__tile"}
-              (dom/img #js {:src "/img/logo.png" :height "40" :width "40" :style #js {:marginTop "2px"}})
-              (dom/span #js {:className "u-font-size--semi-medium"
-                             :style     #js {:position   "relative"
-                                             :top        "-12px"
-                                             :marginLeft "10px"}} "UI Styleguide")))
-          (dom/div #js {:className "u-column"
-                        :style     #js {:marginTop "8px"}}
-            (tabs this :parts/selected-part part-names))
-          (dom/div #js {:className "u-column--3 u-end u-hide@sm u-hide@md"}
-            (ui-search searchbar))
-          )
-        (dom/div #js {:className "ui-parts"}
-          (ui-part (nth parts selected-part)))))))
+        (dom/header #js {:className "o-header"}
+          (dom/div #js {:className "o-toolbar o-toolbar--framed u-row--collapse u-trailer--half"}
+           (dom/div #js {:className "u-column--4 u-column--3@md u-column--2@lg u-middle"}
+             (dom/div #js {:className "o-toolbar__tile"}
+               (dom/img #js {:src "/img/logo.png" :height "40" :width "40" :style #js {:marginTop "2px"}})
+               (dom/span #js {:className "u-font-size--semi-medium"
+                              :style     #js {:position   "relative"
+                                              :top        "-12px"
+                                              :marginLeft "10px"}} "UI Styleguide")))
+           (dom/div #js {:className "u-column"
+                         :style     #js {:marginTop "8px"}}
+             (tabs this :parts/selected-part part-names))
+           (dom/div #js {:className "u-column--3 u-end u-hide@sm u-hide@md"}
+             (ui-search searchbar))
+           ))
+        (dom/main #js {:className "o-main"}
+          (dom/article #js {:className "o-article has-toolbar"}
+            (dom/div #js {:className "ui-parts"}
+             (ui-part (nth parts selected-part)))))))))

 (def ui-parts (om/factory Parts))


New trial on problem 0044. Too slow ?!?!

--- src/project_euler/problem_0044.clj
+++ src/project_euler/problem_0044.clj
@@ -24,7 +24,7 @@
           (< x y) nil
           :else (recur yys))))

-(defn solution []
+(defn solution1 []
   (loop [[d & seq-next-d] (seq-pentagonals)]
     (let [jk (loop [[j & seq-next-j] seq-next-d]
                (let [k (+ d j)
@@ -38,5 +38,51 @@
         jk
         (recur seq-next-d)))
     )
-
   )
+
+(defn solution2 []
+  (loop [[d & seq-next-d] (seq-pentagonals)]
+    (let [jk (loop [[j & seq-next-j] seq-next-d]
+               (let [k (+ d j)
+                     ks (search-in-ordered-seq k seq-next-j)]
+                 (cond ks (do (println d j k)
+                              (cond (search-in-ordered-seq (+ k j) ks) [j k]
+                                    (<= (- (first seq-next-j) j) d) (recur seq-next-j)
+                                    :else false
+                                    ))
+                       (<= (- (first seq-next-j) j) d) (recur seq-next-j)
+                       :else false
+                       )
+                 ))]
+      (if jk
+        jk
+        (recur seq-next-d)))
+    )
+  )
+
+(defn pentagonal [n] (/ (* n (- (* 3 n) 1)) 2))
+
+(defn is-pentagonal? [p]
+  (let [delta (+ 0.25 (* 6 p))
+        x (int (+ 0.5 (/ (+ 0.5 (Math/sqrt delta)) 3)))]
+    (== p (pentagonal x))
+    ))
+
+(defn solution []
+  (->> (iterate inc 1)
+       (map (fn [nd] [nd (pentagonal nd)]))
+       (map (fn [[nd d]] (do (println d) [nd d])))
+       (mapcat (fn [[nd d]]
+                 (->> (iterate inc nd)
+                      (map (fn [nj]
+                             (let [j (pentagonal nj)
+                                   dj (- (pentagonal (inc nj)) j)]
+                               [j dj])))
+                      (take-while (fn [[j dj]] (<= dj d)))
+                      (map (fn [[j dj]] [d j]))
+                               )))
+       (filter (fn [[d j]] (and (is-pentagonal? (+ j d))
+                                (is-pentagonal? (+ j j d)))))
+       (first)
+       ))
+


Remove inline tests in favor of dedicated test files

--- clojure/src/euler/001.clj
+++ clojure/src/euler/001.clj
@@ -15,21 +15,13 @@
 (defn multiples-3-and-5-sol1 [min max]
   (reduce + (filter multiple-of-3-or-5? (range min max))))

-(is (= 233168 (multiples-3-and-5-sol1 0 1000)))
-
-
 ; Use `distinct` instead
 (defn multiples-3-and-5-sol2 [min max]
   (reduce + (distinct (concat (range min max 3)
                               (range min max 5)))))
-
-(is (= 233168 (multiples-3-and-5-sol2 0 1000)))
-

 ; Produce two ranges and convert to `set` to deduplicate the range
 ; Apparently slightly more performant (but who cares)
 (defn multiples-3-and-5-sol3 [min max]
   (reduce + (set (concat (range min max 3)
                          (range min max 5)))))
-
-(is (= 233168 (multiples-3-and-5-sol3 0 1000)))


Fix url validation

Fix url validation

Accept http and https


Include name in copyright.

Include name in copyright.

--- src/stuttaford/web/layout/html.clj
+++ src/stuttaford/web/layout/html.clj
@@ -45,9 +45,9 @@
     "I'm on " [:a {:href twitter} "Twitter"]
     " and " [:a {:href github} "GitHub"] "."]])

-(defnk foot [google-analytics-id domain year]
+(defnk foot [google-analytics-id domain year [:author name]]
   [:div.footer
-   [:p "© " year ". All rights reserved."]
+   [:p "© " name " " year ". All rights reserved. Some lefts, too."]
    [:script {:type "text/javascript"}
     "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
     (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),


(SERVER-548) Address PR comment about comment

--- src/clj/puppetlabs/services/legacy_routes/legacy_routes_core.clj
+++ src/clj/puppetlabs/services/legacy_routes/legacy_routes_core.clj
@@ -101,16 +101,8 @@
         (-> request
           (map-accept-s-to-binary)
           (remove-accept-pson))))
-    ;; TODO: file_bucket_file request PUTs from Puppet agents currently use a
-    ;; Content-Type of 'text/plain', which, per HTTP specification, would imply
-    ;; a default character encoding of ISO-8859-1 or US-ASCII be used to decode
-    ;; the data.  This would be incorrect to do in this case, however, because
-    ;; the actual payload is "binary".  Coercing this to
-    ;; "application/octet-stream" for now as this is synonymous with "binary".
-    ;; This should be removed when/if Puppet agents start using an appropriate
-    ;; Content-Type to describe the input payload - see PUP-3812 for the core
-    ;; Puppet work and SERVER-294 for the related Puppet Server work that
-    ;; would be done.
+    ;; Coercing Content-Type to "application/octet-stream" for Puppet 4
+    ;; compatibility.
     (compojure/PUT "/file_bucket_file/*" request
       (master-request-handler
         (-> request


namespace rename

namespace rename

--- src/dj/codeloading/namespace.clj
+++ src/dj/codeloading/namespace.clj
@@ -15,7 +15,7 @@
                                       :exclusions [[org.clojure/clojure]]]]}
     dj.codeloading.namespace
   (:require [dj]
-            [dj.classloader :as dc]
+            [dj.classreloader :as dc]
             [dj.codeloading.maven :as dcm]
             [clojure.tools.namespace.file :as ctnf]
             [clojure.tools.namespace.parse :as ctnp]


Fix String getting called as function in assert :)

--- src/containium/deployer.clj
+++ src/containium/deployer.clj
@@ -76,8 +76,8 @@
         (println "Starting filesystem deployment watcher, using config" config "...")
         (assert (:deployments config) "Missing :deployments configuration for FS system.")
         (let [dir (file (:deployments config))]
-          (assert (.exists dir) ("The directory " dir " does not exist."))
-          (assert (.isDirectory dir) (str "Path " dir " is not a directory."))
+          (assert (.exists dir) (str "The directory '" dir "' does not exist."))
+          (assert (.isDirectory dir) (str "Path '" dir "' is not a directory."))
           (register-notifier! manager "fs-deployer" (partial handle-notification dir))
           (let [watcher (-> (mk-watchservice (partial handle-event manager dir))
                             (watch dir))]


fix import

fix import

--- src/neuseg/db.clj
+++ src/neuseg/db.clj
@@ -2,7 +2,8 @@
   (:use [clj-tuple]
         [clojure.core.matrix :only [set-current-implementation
                                     new-matrix set-row! get-row
-                                    dot zero-vector normalise]]))
+                                    dot zero-vector normalise]])
+  (:import [com.guokr.neuseg.util NGram]))

 (set-current-implementation :vectorz)


add event_type to profile_data

add event_type to profile_data

--- src/kixi/hecuba/api/profiles.clj
+++ src/kixi/hecuba/api/profiles.clj
@@ -45,6 +45,7 @@

 (def profile-data-schema
   [ :id
+    :event_type
     :occupancy_under_18
     :onsite_days_new_build
     :flat_floor_heat_loss_type


fix update-stringified-lists invocation

fix update-stringified-lists invocation

bru writes 100 times on the blackboard: _always use kebab-case keywords
when in clojure context_

--- src/kixi/hecuba/api/profiles.clj
+++ src/kixi/hecuba/api/profiles.clj
@@ -36,38 +36,31 @@
                 ))
       false)))

-(defn index-post! [querier commander ctx]
-  (let [{:keys [request body]} ctx
-        entity-id     (-> request :route-params :entity-id)
+(defn index-post! [commander querier ctx]
+  (let [request       (-> ctx :request)
+        profile       (-> ctx :body)
+        entity-id     (-> profile :entity-id)
+        timestamp     (-> profile :timestamp)
         [username _]  (sec/get-username-password request querier)
-        user-id       (-> (hecuba/items querier :user [[= :username username]]) first :id)]
-
-    (when-not (empty? (first (hecuba/items querier :entity [[= :id entity-id]])))
-      (let [profile   (-> body
-                          (assoc :user-id user-id)
-                          (update-in [:profile-data] json/encode)
-                          ;; here goes the list of "stuff" associated with profiles
-                          (update-stringified-lists [:airflow_measurements
-                                                    :chps :conservatories
-                                                    :door_sets
-                                                    :extensions
-                                                    :floors
-                                                    :heat_pumps
-                                                    :heating_systems
-                                                    :hot_water_systems
-                                                    :low_energy_lights
-                                                    :photovoltaics
-                                                    :roof_rooms
-                                                    :roofs
-                                                    :small_hydros
-                                                    :solar_thermals
-                                                    :storeys
-                                                    :thermal-images
-                                                    :walls
-                                                    :wind_turbines
-                                                    :window_sets]))
-            profile-id (hecuba/upsert! commander :profile profile)]
-        {:profile-id profile-id}))))
+        user-id       (-> (hecuba/items querier :user [[= :username username]]) first :id)
+        ]
+    (when (and entity-id timestamp)
+      (when-not (empty? (hecuba/item querier :entity entity-id))
+        {:profile-id (hecuba/upsert!
+                        commander
+                        :profile (-> profile
+                                     (assoc :user-id user-id)
+                                     (update-stringified-lists
+                                       [:airflow-measurements :chps
+                                        :conservatories :door-sets
+                                        :extensions :floors :heat-pumps
+                                        :heating-systems :hot-water-systems
+                                        :low-energy-lights :photovoltaics
+                                        :roof-rooms :roofs :small-hydros
+                                        :solar-thermals :storeys :thermal-images
+                                        :walls :wind-turbines :window-sets])
+                                     (update-in [:profile-data] json/encode)
+                                     ))}))))

 (defn index-handle-ok [ctx]
   (let [{items ::items
@@ -101,7 +94,7 @@
                                             :status "OK"
                                             :version "4"})}))
       (ring-response {:status 422
-                      :body "Provide valid projectId and propertyCode."}))))
+                      :body "Provide valid entityId and timestamp."}))))

 (defn resource-exists? [querier ctx]
   (let [{{{:keys [entity-id profile-id]} :route-params} :request} ctx
@@ -160,7 +153,7 @@
   :authorized? (authorized? querier :profile)
   :exists? (partial index-exists? querier)
   :malformed? index-malformed?
-  :post! (partial index-post! querier commander)
+  :post! (partial index-post! commander querier)
   :handle-ok (partial index-handle-ok)
   :handle-created (partial index-handle-created handlers))


Still use the bell as a default.

Still use the bell as a default.

--- src/klangmeister/processing.cljs
+++ src/klangmeister/processing.cljs
@@ -29,7 +29,7 @@
   (process [this handle! {:keys [music looping?] :as state}]
     (if looping?
       (let [start (Date.now)]
-        (music/play-on! instrument/fuzz! music)
+        (music/play-on! instrument/bell! music)
         (js/setTimeout #(handle! this) (music/duration music))
         (assoc state :sync start))
       (dissoc state :sync))))


polyfill isMounted check

polyfill isMounted check

--- src/rum/core.cljs
+++ src/rum/core.cljs
@@ -39,12 +39,12 @@

         ctor (fn [props]
                (this-as this
-                 (set! (.-state this)
-                       #js {":rum/state"
-                            (-> (gobj/get props ":rum/initial-state")
-                                (assoc :rum/react-component this)
-                                (call-all init props)
-                                volatile!)})
+                 (gobj/set this "state"
+                           #js {":rum/state"
+                                (-> (gobj/get props ":rum/initial-state")
+                                    (assoc :rum/react-component this)
+                                    (call-all init props)
+                                    volatile!)})
                  (.call js/React.Component this props)))]

     (gobj/set ctor "displayName" display-name)
@@ -56,9 +56,10 @@
              (this-as this
                (vswap! (state this) call-all will-mount))))
          :componentDidMount
-         (when-not (empty? did-mount)
-           (fn []
-             (this-as this
+         (fn []
+           (this-as this
+             (gobj/set this ":rum/mounted?" true)
+             (when-not (empty? did-mount)
                (vswap! (state this) call-all did-mount))))
          :componentWillReceiveProps
          (fn [next-props]
@@ -95,10 +96,11 @@
              (this-as this
                (vswap! (state this) call-all did-update))))
          :componentWillUnmount
-         (when-not (empty? will-unmount)
-           (fn []
-             (this-as this
-               (vswap! (state this) call-all will-unmount))))
+         (fn []
+           (this-as this
+             (when-not (empty? will-unmount)
+               (vswap! (state this) call-all will-unmount))
+             (gobj/set this ":rum/mounted?" false)))
          :getChildContext
          (when-not (empty? child-context)
            (fn []
@@ -169,7 +171,8 @@

 (defn- render-all [queue]
-  (doseq [comp queue]
+  (doseq [comp queue
+          :when (gobj/get comp ":rum/mounted?")]
     (.forceUpdate comp)))


Serialize java.time.ZoneRegion

Serialize java.time.ZoneRegion

--- src/tick/ical.clj
+++ src/tick/ical.clj
@@ -9,7 +9,7 @@
    [tick.core :as t]
    [tick.interval :as ival])
   (:import
-   [java.time Instant LocalDate LocalDateTime ZonedDateTime ZoneId]
+   [java.time Instant LocalDate LocalDateTime ZonedDateTime ZoneId ZoneRegion]
    [java.time.format DateTimeFormatter]))

 ;; Have considered wrapping ical4j. However, since ical4j does not
@@ -65,6 +65,8 @@
   ZonedDateTime
   (serialize-value [s] {:value (.format s DATE-TIME-FORM-3-PATTERN)
                         :params {:tzid (t/zone s)}})
+  ZoneRegion
+  (serialize-value [zr] {:value (str zr)})
   clojure.lang.APersistentMap
   (serialize-value [s] s))


Add route to ping niantic server

Add route to ping niantic server

--- frontend/src/cruncher/config.cljs
+++ frontend/src/cruncher/config.cljs
@@ -8,4 +8,5 @@
           :toggle-favorite "api/pokemon/favorite"
           :crunch-selected-pokemon "api/pokemon/delete"
           :status-delete "api/status/delete"
-          :get-player "api/player"})
+          :get-player "api/player"
+          :api-status "api/status/niantic"})


Continuous deployment, for real

Continuous deployment, for real

--- src/eulalie/instance_data.clj
+++ src/eulalie/instance_data.clj
@@ -34,15 +34,15 @@
 (defn meta-data!
   "(meta-data! [:iam :security-credentials])"
   [path & [args]]
-  (retrieve! path (flatten (conj [:latest :meta-data] path))))
+  (retrieve! (flatten (conj [:latest :meta-data] path)) args))
 (def meta-data!! (comp util/<?! meta-data!))

 (defn instance-identity!
   "(instance-identity! :document {:parse-json true})"
   [path & [args]]
   (retrieve!
-   path
-   (flatten (conj [:latest :dynamic :instance-identity] path))))
+   (flatten (conj [:latest :dynamic :instance-identity] path))
+   args))

 (def instance-identity!! (comp util/<?! instance-identity!))


Enable async subscription.

Enable async subscription.

--- src/futura/stream/channel.clj
+++ src/futura/stream/channel.clj
@@ -95,13 +95,11 @@
                this
                subscriber)]
       (.add ^Set subscriptions sub)
-      (try
-        (.onSubscribe subscriber sub)
-        (catch Throwable t
-          (terminate sub (IllegalStateException. "Violated the Reactive Streams rule 2.13"))))
-      ;; Temporary avoid async subscription because
-      ;; Ratpack has a bug with them: https://github.com/ratpack/ratpack/issues/682
-      ;; (signal-subscribe sub)
+      ;; (try
+      ;;   (.onSubscribe subscriber sub)
+      ;;   (catch Throwable t
+      ;;     (terminate sub (IllegalStateException. "Violated the Reactive Streams rule 2.13"))))
+      (signal-subscribe sub)
       sub)))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


RR: :assoc-in to specific key

RR: :assoc-in to specific key

--- src/hatti/views/dataview.cljs
+++ src/hatti/views/dataview.cljs
@@ -111,10 +111,10 @@
        shared/app-state
        (fn [app-state]
          (-> app-state
-             (assoc-in [:views: :selected] view)
-             (assoc-in [:views :settings] {:active-tab settings-section})
-             (assoc-in [:views :settings :integrated-apps]
-                       {:active-section app-type}))))
+             (assoc-in [:views :selected] view)
+             (assoc-in [:views :settings :active-tab] settings-section)
+             (assoc-in [:views :settings :integrated-apps :active-section]
+                       app-type))))
       (if (= app-type google-sheets)
         (merge-into-app-state! shared/app-state
                                [:views :settings :integrated-apps]


Cleanup the pipeline tests a bit

Cleanup the pipeline tests a bit

--- test/picard/test/core/pipeline.clj
+++ test/picard/test/core/pipeline.clj
@@ -72,15 +72,12 @@
          1 inc (fn [_] (throw (Exception.)))
          (finally (res2 :world)))
         (receive identity))
-    (is (= :world @res2))
-    ))
+    (is (= :world @res2))))

 (deftest nesting-pipelines
   (let [res (promise)]
     (-> (pipeline
-         1
-         #(pipeline % async-inc async-inc)
-         inc)
+         1 #(pipeline % async-inc async-inc) inc)
         (receive #(res %)))
     (is (= 4 @res))))


Target JDK 6

Target JDK 6

--- android/project.clj
+++ android/project.clj
@@ -7,7 +7,7 @@

   :source-paths ["src/clojure" "../common/clojure"]
   :java-source-paths ["src/java" "../common/java" "gen"]
-  :javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"]
+  :javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]

   :dependencies [[com.h2database/h2 "1.3.174"]
                  [markdown-clj "0.9.36"]


Checked with 'kibit' static analyzer

Checked with 'kibit' static analyzer

--- process-clojure/project.clj
+++ process-clojure/project.clj
@@ -6,4 +6,5 @@
     [org.clojure/data.csv "0.1.2"]]
   :main ^:skip-aot process.core
   :target-path "target/%s"
-  :profiles {:uberjar {:aot :all}})
+  :profiles {:uberjar {:aot :all}}
+  :plugins [[lein-kibit "0.1.2"]])


defonce only the first time

defonce only the first time

--- src/nha/boot_uglify/uglifyjs.clj
+++ src/nha/boot_uglify/uglifyjs.clj
@@ -56,13 +56,17 @@

 ;; To avoid creating a new Nashorn engine
 ;; and evaluate UglifyJS every time
-;; TODO lazy creation?
-(defonce js-engine (create-uglify-engine))
+;; but not use memory as soon as the ns is loaded
+(defn maybe-init-uglify-engine []
+  (defonce js-engine (create-uglify-engine)))
+

 (defn uglify-str
   "Minify a String using Uglify-JS2"
   ([^String s] (uglify-str s {}))
-  ([^String s opts] (uglify-str* js-engine s opts)))
+  ([^String s opts]
+   (maybe-init-uglify-engine)
+   (uglify-str* js-engine s opts)))

 (comment


keywordize wrapped exception class

keywordize wrapped exception class

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -331,7 +331,7 @@

 (defn deserializable-exception [^Throwable throwable]
   (let [{:keys [data trace]} (Throwable->map throwable)
-        data (assoc data :original-exception-name (.getName (.getClass throwable)))]
+        data (assoc data :original-exception (keyword (.getName (.getClass throwable))))]
     (doto ^Throwable (ex-info (.getMessage throwable) data)
       (.setStackTrace (into-array StackTraceElement trace)))))


removed unused annotation

removed unused annotation

--- src/gif_to_html/convert.clj
+++ src/gif_to_html/convert.clj
@@ -48,6 +48,6 @@
                   [:pre
                    {:id (str "frame-" i)
                     :style "font-size:6pt; letter-spacing:1px; line-height:6pt; font-weight:bold; display: none;font-family:monospace;"}
-                   (to-ascii (scale-image (.read ^ImageReader rdr i) w h))])
+                   (to-ascii (scale-image (.read rdr i) w h))])
                (range frame-count))])
        :frames frame-count})))


Remove reflection warning

Remove reflection warning

--- src/github_changelog/fs.clj
+++ src/github_changelog/fs.clj
@@ -3,8 +3,6 @@
   (:import java.io.File
            [java.nio.file Files FileVisitResult Path SimpleFileVisitor]
            java.nio.file.attribute.FileAttribute))
-
-(set! *warn-on-reflection* true)

 (def empty-file-attrs (into-array FileAttribute []))


Modified Benchmark to output Checksum in the beginning.

--- shootout/base.clj
+++ shootout/base.clj
@@ -3,17 +3,15 @@

 ;; ## String Hashing

-(def ^:const ^String HELLO_WORLD "Hello, World!")
-
 (defmacro bench-hash-function
-  [& fs]
+  [string & fs]
   `(do
      ~@(for [f fs]
          `((println "----------------------------------------------------")
            (println ~(str "Benchmarking: " f))
            (println "----------------------------------------------------")
-           (println ~(str "Hashing \"" HELLO_WORLD "\""))
-           (quick-bench (~f ~HELLO_WORLD))
+           (println (str "Hashing String: " ~string " (" (~f ~string) ")"))
+           (quick-bench (~f ~string))
            (println "----------------------------------------------------")))))

 ;; ## File Hashing
@@ -25,7 +23,7 @@
          `((println "----------------------------------------------------")
            (println ~(str "Benchmarking: " f))
            (println "----------------------------------------------------")
-           (println ~(str "Hashing File:") ~file)
+           (println (str "Hashing File: " ~file " (" (~f ~file) ")"))
            (quick-bench (~f ~file))
            (println "----------------------------------------------------")))))

@@ -42,9 +40,12 @@
            ~@(doall
                (mapcat
                  (fn [[flag [f1 f2]]]
-                   [flag `(if (and ~f2 (= ~t "--file"))
-                            (bench-file-hash-function (first ~args) ~f2)
-                            (bench-hash-function ~f1))])
+                   [flag `(case ~t
+                            "--file" (bench-file-hash-function (first ~args) ~f2)
+                            "--text" (bench-hash-function (first ~args) ~f1)
+                            (bench-hash-function "Hello, World!" ~f1))])
                  (partition 2 hash-fn-map)))
            (println "Unknown Algorithm: " algorithm#))
-         (catch Exception _# nil)))))
+         (catch NullPointerException e# nil)
+         (catch Exception e#
+           (.printStackTrace e#))))))


CMR-3703 adds comment detailing potential bug in iso_shared/distributios_related_url.clj

--- umm-spec-lib/src/cmr/umm_spec/xml_to_umm_mappings/iso_shared/distributions_related_url.clj
+++ umm-spec-lib/src/cmr/umm_spec/xml_to_umm_mappings/iso_shared/distributions_related_url.clj
@@ -175,5 +175,7 @@
   {:URL (value-of url "gmd:linkage/gmd:URL")
    :Description (:Description types-and-desc)
    :URLContentType (or (:URLContentType types-and-desc) "PublicationURL")
+   ;; Type VIEW RELATED INFORMATION is invalid for many URLContentTypes, so this will fail
+   ;; URLContentType/Type/SubType custom validation for RelatedUrls.
    :Type (or (:Type types-and-desc) "VIEW RELATED INFORMATION")
    :Subtype (:Subtype types-and-desc)}))


CMR-4449: Added test for cascading delete.

--- system-int-test/test/cmr/system_int_test/search/variable/variable_revisions_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/variable/variable_revisions_search_test.clj
@@ -4,7 +4,9 @@
    [clojure.test :refer :all]
    [cmr.common.util :refer [are3]]
    [cmr.mock-echo.client.echo-util :as e]
+   [cmr.system-int-test.data2.core :as d]
    [cmr.system-int-test.data2.umm-json :as du]
+   [cmr.system-int-test.data2.umm-spec-collection :as data-umm-c]
    [cmr.system-int-test.system :as s]
    [cmr.system-int-test.utils.index-util :as index]
    [cmr.system-int-test.utils.ingest-util :as ingest]
@@ -20,6 +22,9 @@

 (deftest search-variable-all-revisions
   (let [token (e/login (s/context) "user1")
+        coll1 (d/ingest-umm-spec-collection "PROV1"
+                                            (data-umm-c/collection 1 {})
+                                            {:token token})
         var1-concept (variables/make-variable-concept {:native-id "var1"
                                                        :Name "Variable1"
                                                        :provider-id "PROV1"})
@@ -124,7 +129,22 @@
       ;; force deleted revisions are no longer in the search result
       (variables/assert-variable-references-match
        [var1-2-tombstone var1-3 var2-1 var2-2 var3]
-       (search/find-refs :variable {:all-revisions true})))))
+       (search/find-refs :variable {:all-revisions true}))
+
+      (testing "force delete cascade to variable association"
+        (variables/associate-by-concept-ids token
+                                            (:concept-id var1-3)
+                                            [{:concept-id (:concept-id coll1)}])
+        (index/wait-until-indexed)
+        ;; search collections by variable native-id found the collection
+        (d/refs-match? [coll1] (search/find-refs :collection {:variable_native_id "var1"}))
+
+        ;; force delete the latest revision of the variable cascade to variable association
+        (metadata-db/force-delete-concept (:concept-id var1-3) (:revision-id var1-3))
+        (index/wait-until-indexed)
+
+        ;; search collections by variable native-id no longer found the collection
+        (d/refs-match? [] (search/find-refs :collection {:variable_native_id "var1"}))))))

 (deftest search-all-revisions-error-cases
   (testing "variable search with all_revisions bad value"


[#3036] (RE)use ::db.dsv.column.s/columnName instead of string?

--- backend/specs/akvo/lumen/specs/transformation.clj
+++ backend/specs/akvo/lumen/specs/transformation.clj
@@ -11,8 +11,6 @@
             [clojure.string :as string]
             [clojure.tools.logging :as log])
   (:import [java.time Instant]))
-
-(def columnName? string?)

 (s/def ::type #{:transformation :undo})

@@ -174,8 +172,8 @@
 (create-ns  'akvo.lumen.specs.transformation.generate-geopoints)
 (alias 'transformation.generate-geopoints 'akvo.lumen.specs.transformation.generate-geopoints)

-(s/def ::transformation.generate-geopoints/columnNameLat columnName?)
-(s/def ::transformation.generate-geopoints/columnNameLong columnName?)
+(s/def ::transformation.generate-geopoints/columnNameLat ::db.dsv.column.s/columnName)
+(s/def ::transformation.generate-geopoints/columnNameLong ::db.dsv.column.s/columnName)
 (s/def ::transformation.generate-geopoints/columnTitleGeo string?)

@@ -216,7 +214,7 @@
                                                         ::transformation.merge-datasets.source/mergeColumn
                                                         ::transformation.merge-datasets.source/mergeColumns]))

-(s/def ::transformation.merge-datasets.target/mergeColumn columnName?)
+(s/def ::transformation.merge-datasets.target/mergeColumn ::db.dsv.column.s/columnName)

 (s/def ::transformation.merge-datasets/target (s/keys :req-un [::transformation.merge-datasets.target/mergeColumn]))
@@ -406,7 +404,7 @@
 (alias 'transformation.sort-column 'akvo.lumen.specs.transformation.sort-column)

 (s/def ::transformation.sort-column/sortDirection lumen.s/sort?)
-(s/def ::transformation.sort-column/columnName columnName?)
+(s/def ::transformation.sort-column/columnName ::db.dsv.column.s/columnName)

 (s/def ::transformation.sort-column/args
   (s/keys :req-un [::transformation.sort-column/sortDirection
@@ -423,7 +421,7 @@
 (create-ns  'akvo.lumen.specs.transformation.remove-sort)
 (alias 'transformation.remove-sort 'akvo.lumen.specs.transformation.remove-sort)

-(s/def ::transformation.remove-sort/columnName columnName?)
+(s/def ::transformation.remove-sort/columnName ::db.dsv.column.s/columnName)

 (s/def ::transformation.remove-sort/args
   (s/keys :req-un [::transformation.remove-sort/columnName]))


make a convenience function to facilitate listening to Figwheel messages

--- support/src/figwheel/client.cljs
+++ support/src/figwheel/client.cljs
@@ -443,6 +443,9 @@
    socket/message-history-atom key
    (fn [_ _ _ msg-hist] (callback (first msg-hist)))))

+(defn ^:export add-json-message-watch [key callback]
+  (add-message-watch key (comp callback clj->js)))
+
 (defn add-plugins [plugins system-options]
   (doseq [[k plugin] plugins]
     (when plugin


when deleting node, delete also trailing whitespace

--- cljs/src/main/plastic/cogs/editor/model.cljs
+++ cljs/src/main/plastic/cogs/editor/model.cljs
@@ -2,7 +2,7 @@
   (:require-macros [plastic.macros.logging :refer [log info warn error group group-end]])
   (:require [rewrite-clj.zip :as zip]
             [rewrite-clj.zip.findz :as findz]
-            [rewrite-clj.node.protocols :as node]
+            [rewrite-clj.node :as node]
             [clojure.walk :refer [prewalk]]
             [plastic.cogs.editor.parser.utils :as parser]
             [plastic.util.helpers :as helpers]
@@ -201,10 +201,17 @@
       (z/edit node-loc (fn [old-node] (transfer-sticky-attrs old-node new-node)))
       (z/remove node-loc))))

+(defn delete-whitespaces-and-newlines-after-loc [loc]
+  (loop [cur-loc loc]
+    (let [possibly-white-space-loc (z/right cur-loc)]
+      (if (and (zip-utils/valid-loc? possibly-white-space-loc) (node/whitespace? (zip/node possibly-white-space-loc)))
+        (recur (z/remove possibly-white-space-loc))
+        cur-loc))))
+
 (defn delete-node-loc [node-id loc]
   (let [node-loc (findz/find-depth-first loc (partial loc-id? node-id))]
     (assert (zip-utils/valid-loc? node-loc))
-    (z/remove node-loc)))
+    (z/remove (delete-whitespaces-and-newlines-after-loc node-loc))))

 (defn parse-tree-transformer [f]
   (fn [parse-tree]


[lein] Bump lein-ancient

[lein] Bump lein-ancient

--- .lein/profiles.clj
+++ .lein/profiles.clj
@@ -1,6 +1,6 @@
 {:user {:plugins [[lein-cloverage                    "1.0.2"]
                   [lein-fore-prob                    "0.1.2"]
-                  [lein-ancient                      "0.5.4"]
+                  [lein-ancient                      "0.6.10"]
                   [jonase/eastwood                   "0.2.3"]
                   [com.jakemccrary/lein-test-refresh "0.3.4"]
                   [lein-pprint                       "1.1.1"]


add subcat terminator to subcat-principle-5 rule

--- src/babel/ug.cljc
+++ src/babel/ug.cljc
@@ -168,7 +168,8 @@
                               :3 subcat-3}}}
      :comp {:synsem subcat-3}
      :synsem {:subcat {:1 subcat-1
-                       :2 subcat-2}}}))
+                       :2 subcat-2
+                       :3 '()}}}))

 (def comp-modifies-head
   (let [human (atom :top)


pathc

pathc

--- src/ci3/build.clj
+++ src/ci3/build.clj
@@ -92,7 +92,7 @@
 (defn update-status [build]
   (let [gh-status  (gh/set-status build)
         id (get-in build [:metadata :name])]
-    (k8s/patch k8s/cfg :build id
+    (k8s/patch k8s/cfg :builds id
                {:gh-status gh-status})) )

 (defn build [build]


(SERVER-548) Fail the unit tests if header assertions are skipped

Without this patch there is the possibility that the assertions made
against the munged request are not executed.  This is a problem because
there could be an issue with the routes which are not caught by the unit
tests.  This patch addresses the problem by creating an Atom and
wrapping the assertions made from a downstream middleware in a function
that updates the Atom when triggered.  The patch makes a subsequent
assertion against the Atom to make sure it was updated by the
assertion function.

--- test/unit/puppetlabs/services/legacy_routes/legacy_routes_core_test.clj
+++ test/unit/puppetlabs/services/legacy_routes/legacy_routes_core_test.clj
@@ -41,10 +41,10 @@

   {path {method {example expected}}}"
   {
-   "/" {:head {"raw" "raw"}
-        :post {"raw" "raw"}
-        :get {"raw" "raw"
-              "foo,bar" "foo,bar"}}
+   "/production/node/anode" { :get {"raw" "binary"
+                                    "foo,bar" "foo, bar"}}
+   "/production/facts/anode" { :get {"raw" "binary"
+                                     "foo,bar" "foo, bar"}}
    "/production/catalog/anode" {:get accept-header-raw-examples
                                 :post accept-header-raw-examples}
    "/production/file_content/something" {:get accept-header-raw-examples}
@@ -75,7 +75,11 @@
   "Validate a request by threading it through the legacy-routes request handler
   into an assertion-wrapper ring middleware."
   [request assertion]
-  ((validating-app assertion) request))
+  (let [mem (atom {:tested false})
+        wrapped-assertion #((swap! mem assoc :tested true) (assertion %))
+        response ((validating-app wrapped-assertion) request)]
+    (is (true? (:tested @mem)) (str "request not tested: " (pr-str request)))
+    response))

 (deftest test-legacy-routes
   (let [app     (build-ring-handler
@@ -143,8 +147,4 @@
         (test-munged-request request
           (fn [munged-request] ; ring middleware
             (let [actual (get-in munged-request content-type-header)]
-              (is (= "application/octet-stream" actual)))))
-        (test-munged-request request
-          (fn [munged-request] ; ring middleware
-            (let [actual (get-in munged-request content-type-header)]
               (is (= "application/octet-stream" actual)))))))))


feat(handler): add handler to send image message, add condition for help

--- clojure/compojure-bot/src/compojure_bot/facebook.clj
+++ clojure/compojure-bot/src/compojure_bot/facebook.clj
@@ -2,7 +2,8 @@
   (:gen-class)
   (:require [org.httpkit.client :as http]
             [clojure.pprint :as pprint]
-            [clojure.data.json :as json]))
+            [clojure.data.json :as json]
+            [clojure.string :as s]))

 (defn webhook-is-valid? [request]
   (def params (:params request))
@@ -29,11 +30,21 @@
     (println messageData)
     (sendAPI messageData))

+(defn sendImageMessage [[recipientId imageUrl]]
+    (def messageData {:recipient {:id recipientId} :message {:attachment {:type "image" :payload {:url imageUrl}}}})
+    (println messageData)
+    (sendAPI messageData))
+
 (defn onMessage [event]
   (let [senderID (get-in event [:sender :id]) recipientID (get-in event [:recipient :id]) timeOfMessage (get-in event [:timestamp]) message (get-in event [:message])]
     (println (str "Received message for user " senderID " and page " recipientID " at " timeOfMessage " with message:"))
     (println message)
-    [senderID (:text message)]))
+    (println (:text message))
+    ; Add rules here
+    (cond
+      (s/includes? (s/lower-case (:text message)) "help") (sendTextMessage [senderID "Hi there, happy to help :)"])
+      (s/includes? (s/lower-case (:text message)) "image") (sendImageMessage [senderID "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/1280px-M101_hires_STScI-PRC2006-10a.jpg"])
+      :else (sendTextMessage [senderID (:text message)]))))

 (defn route-request [request]
   (def data (get-in request [:params]))
@@ -42,5 +53,6 @@
   (if (= (:object data) "page")
     (doseq [pageEntry (:entry data)]
       (doseq [messagingEvent (:messaging pageEntry)]
-        (cond (contains? messagingEvent :message) (sendTextMessage (onMessage messagingEvent))
+        ; Check for text or attachments here
+        (cond (contains? messagingEvent :message) (onMessage messagingEvent)
           :else (println (str "Webhook received unknown messagingEvent: " messagingEvent)))))))


new cljsjs setup

new cljsjs setup

--- src/leiningen/new/tenzing.clj
+++ src/leiningen/new/tenzing.clj
@@ -68,16 +68,16 @@
 (defn dependencies [opts]
   (cond-> ["pandeiro/boot-http \"0.3.0\""]
           (om?      opts) (conj "om \"0.7.3\"" "cljsjs/react \"0.11.2\"")
-          (reagent? opts) (conj "reagent \"0.4.3\"" "cljsjs/react \"0.12.1\"")
+          (reagent? opts) (conj "reagent \"0.4.3\"" "cljsjs/react \"0.12.2-1\"")
           (garden?  opts) (conj "boot-garden \"1.2.5-1\"")
           (sass?    opts) (conj "boot-sassc  \"0.1.0\"")
-          (or (om? opts) (reagent? opts)) (conj "cljsjs/boot-cljsjs \"0.2.3-SNAPSHOT\"")))
+          (or (om? opts) (reagent? opts)) (conj "cljsjs/boot-cljsjs \"0.3.0\"")))

 (defn build-requires [opts]
   (cond-> []
           (garden? opts) (conj "'[boot-garden.core :refer [garden]]")
           (sass?   opts) (conj "'[boot-sassc.core  :refer [sass]]")
-          (or (om? opts) (reagent? opts)) (conj "'[cljsjs.app :refer [js-import]]") ))
+          (or (om? opts) (reagent? opts)) (conj "'[cljsjs.app :refer [from-cljsjs]]") ))

 (defn build-steps [name opts]
   (cond-> []
@@ -106,10 +106,11 @@

 (defn index-html-script-tags [opts]
   (letfn [(script-tag [src] (str "<script type=\"text/javascript\" src=\"" src "\"></script>"))]
-    (conj (cond-> []
-            (or (om? opts) (reagent? opts))
-            (conj (script-tag "js/preamble.js")))
-          (script-tag "js/app.js"))))
+    (cond-> []
+            false ;(or (om? opts) (reagent? opts))
+            (conj (script-tag "js/preamble.js"))
+            :finally
+            (conj (script-tag "js/app.js")))))

 (defn template-data [name opts]
   {:name name


remove submit_job namespace in favor of keeping it

in the template

--- src/lib_onyx/submit_job.clj
+++ src/lib_onyx/submit_job.clj
@@ -1,39 +0,0 @@
-(ns lib-onyx.submit-job
-  (:gen-class)
-  (:require [aero.core :refer [read-config]]
-            [clojure.tools.cli :refer [parse-opts]]
-            [clojure.java.io :as io]
-            [clojure.edn]
-            onyx.api
-            [onyx.job :refer [register-job]]))
-
-(defn job-exists? [job-name]
-  (contains? (methods register-job) job-name ))
-
-(defn file-exists? [file]
-  (let [f (clojure.string/trim file)
-        classf (io/resource file)
-        relf (when (.exists (io/as-file f)) (io/as-file f))]
-    (or classf relf)))
-
-(def cli-options
-  ;; An option with a required argument
-  [["-c" "--config FILE" "Aero/EDN config file"
-    :parse-fn file-exists?
-    :validate [identity "File does not exist relative to the workdir or on the classpath"
-               read-config "Not a valid Aero or EDN file"]]
-   ["-p" "--profile PROFILE" "Aero profile"
-    :parse-fn (fn [profile] (clojure.edn/read-string (clojure.string/trim profile)))]
-   ["-h" "--help"]])
-
-(defn -main
-  "Submit's a registered job to the Onyx cluster"
-  [& args]
-  (let [{:keys [options arguments summary errors]} (parse-opts args cli-options)
-        [job-name] arguments
-        {:keys [profile config]} options
-        parsed-config (read-config config {:profile profile})]
-    (assert (job-exists? job-name) (str "There is no job registered under the name " job-name))
-    (-> (onyx.api/submit-job (:peer-config parsed-config)
-                             (register-job job-name parsed-config))
-        (clojure.pprint/pprint))))


update example

update example

--- example/project.clj
+++ example/project.clj
@@ -1,14 +1,14 @@
 (defproject example "1.0.0-SNAPSHOT"
   :description "Example web app using single-sign-on with couchdb"
-  :dependencies [[org.clojure/clojure "1.3.0"]
+  :dependencies [[org.clojure/clojure "1.4.0"]
                  [org.clojure/data.json "0.1.1"]
                  [org.clojure/tools.logging "0.2.3"]
                  [org.slf4j/log4j-over-slf4j "1.6.4"]
                  [ch.qos.logback/logback-classic "1.0.0"]
                  [compojure "1.0.0"]
                  [org.signaut/ring.middleware.servlet-ext "0.4"]
-                 [ring/ring-core "1.0.2"]
-                 [ring/ring-servlet "1.0.2"]]
+                 [ring/ring-core "1.1.0"]
+                 [ring/ring-servlet "1.1.0"]]
   :dev-dependencies [[swank-clojure "1.2.1"]
                      [ring/ring-devel "1.0.2"]
                      [uk.org.alienscience/leiningen-war "0.0.12"]


Update an example project

Update an example project

--- example/project.clj
+++ example/project.clj
@@ -6,7 +6,7 @@

   ; List of plugins
-  :plugins [[lein-jshint "0.1.8"]]
+  :plugins [[lein-jshint "0.1.9"]]

   ; List of hooks
   ; It's used for running JSHint during compile phase


defining fields: allow symbol and keyword names and auto-cast initial numeric values

--- src/insn/core.clj
+++ src/insn/core.clj
@@ -141,8 +141,13 @@

       (doseq [f (:fields t)]
         (let [flags (:flags f *field-flags*)
-              fv (.visitField cv (util/flags flags) (:name f)
-                              (util/type-desc (:type f)) nil (:value f))]
+              ftype (util/type-desc (:type f))
+              fval (when-let [v (:value f)]
+                     (case ftype
+                       "I" (int v), "J" (long v)
+                       "F" (float v), "D" (double v)
+                       v))
+              fv (.visitField cv (util/flags flags) (name (:name f)) ftype nil fval)]
           (ann/visit fv (:annotations f))
           (.visitEnd fv)))


Remove mount hooks

Remove mount hooks

--- src/iss/core.cljs
+++ src/iss/core.cljs
@@ -40,12 +40,6 @@
 (defmethod even-odd-widget true
   [props owner]
   (reify
-    om/IWillMount
-    (will-mount [_]
-      (println "Even widget mounting"))
-    om/IWillUnmount
-    (will-unmount [_]
-      (println "Even widget unmounting"))
     om/IRender
     (render [_]
       (dom/div #js {:className (.-widget even-odd)}
@@ -58,12 +52,6 @@
 (defmethod even-odd-widget false
   [props owner]
   (reify
-    om/IWillMount
-    (will-mount [_]
-      (println "Odd widget mounting"))
-    om/IWillUnmount
-    (will-unmount [_]
-      (println "Odd widget unmounting"))
     om/IRender
     (render [_]
       (dom/div #js {:className (.-widget even-odd)}


make spinner bigger

make spinner bigger

--- pedestal-app/app/src/semtag_web/spinner.cljs
+++ pedestal-app/app/src/semtag_web/spinner.cljs
@@ -9,9 +9,9 @@
 ;; Based on http://stackoverflow.com/questions/9585752/using-simplemodal-show-loading-spinner-while-content-inside-iframe-loads/12882847#12882847
 (def modal-opts
   {:lines 11
-   :length 23
+   :length 33
    :width 8
-   :radius 40
+   :radius 45
    :corners 1
    :rotate 9
    :color "#FFF"


Check for thread-bound? not just bound?.

--- src/multicodec/codecs/mux.clj
+++ src/multicodec/codecs/mux.clj
@@ -53,7 +53,7 @@
                  (str "No codecs can encode value: " (pr-str value))
                  {:codecs (keys codecs)
                   :value value})))
-      (when (bound? #'*dispatched-codec*)
+      (when (thread-bound? #'*dispatched-codec*)
         (set! *dispatched-codec* codec-key))
       (codec/encode-with-header! codec output value)))

@@ -74,7 +74,7 @@
                  (str "No codecs can decode header: " (pr-str header'))
                  {:codecs (keys codecs)
                   :header header'})))
-      (when (bound? #'*dispatched-codec*)
+      (when (thread-bound? #'*dispatched-codec*)
         (set! *dispatched-codec* codec-key))
       (codec/decode! codec input))))


I probably should have written the test first

I did at least use types, so I should be pretty close... right?

--- src/packager/distributor.cljc
+++ src/packager/distributor.cljc
@@ -5,16 +5,33 @@

 (def Distribution {b/Box [b/Box]})

-(s/defn collect :- [[Distribution]]
+(s/defn process-boxes :- Distribution
+  [boxes :- [b/Box]
+   h :- Number
+   d :- Distribution]
+  (if (seq boxes)
+    (loop [[[bw _ :as b] & bs] boxes
+           w 0.0
+           d d]
+      (let [d' (if (contains? d b)
+                 (merge-with conj d {b [w h]})
+                 (assoc d b [[w h]]))]
+        (if (seq? bs)
+          (recur bs (+ w bw) d')
+          d')))
+    d))
+
+(s/defn collect :- Distribution
   [{shelves :shelves} :- c/Container]
-  (for [{boxes :boxes :as shelf} shelves]
-    (for [box boxes]
-      {box [[0.0 0.0]]})))
+  (loop [[{[_ sh] :dimensions
+           boxes :boxes} & ss] shelves
+         h 0.0
+         d {}]
+    (let [pb (process-boxes boxes h d)]
+      (if (seq ss)
+        (recur ss (+ h sh) pb)
+        pb))))

 (s/defn distribute :- Distribution
   [c :- c/Container]
-  (let [locations (collect c)]
-    (or (->> locations
-             flatten
-             (apply merge-with vector))
-        {})))
+  (collect c))


Send viewers and authors ids with the boards list in org response if requesting user is part of the team, they are needed for the WST.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -289,7 +289,7 @@
                              author-reps (map #(org-rep/render-author-for-collection org % (:access-level ctx)) authors)
                              has-sample-content? (> (entry-res/sample-entries-count conn org-id) 1)]
                          (org-rep/render-org (-> org
-                                                 (assoc :boards (map #(dissoc % :authors :viewers) board-reps))
+                                                 (assoc :boards (if user-is-part-of-the-team? board-reps (map #(dissoc % :authors :viewers) board-reps)))
                                                  (assoc :must-see-count must-see-count)
                                                  (assoc :authors author-reps))
                                              (:access-level ctx)


move the slams out of the maps

move the slams out of the maps

--- src/navigator.clj
+++ src/navigator.clj
@@ -74,15 +74,15 @@
                                    (hatch/slam-all (get-in message [:payload :entity]) :task))))

 (defn comp-in [db-conn message]
-  (tx-entity! db-conn :comp (merge {:comp/id-sk (str (get-in message [:header :entity-id :comp-id]))
-                                    (hatch/slam-all (get-in message [:payload :entity]) :comp)})))
+  (tx-entity! db-conn :comp (merge {:comp/id-sk (str (get-in message [:header :entity-id :comp-id]))}
+                                    (hatch/slam-all (get-in message [:payload :entity]) :comp))))

 (defn comp-tag-in [db-conn message]
   (tx-entity! db-conn :comp-tag (hatch/slam-all (get-in message [:payload :entity]) :comp-tag)))

 (defn perf-asmt-in [db-conn message]
-  (tx-entity! db-conn :perf-asmt (merge {:perf-asmt/id-sk (str (get-in message [:header :entity-id :perf-asmt-id]))
-                                         (hatch/slam-all (get-in message [:paylod :entity]) :perf-asmt)})))
+  (tx-entity! db-conn :perf-asmt (merge {:perf-asmt/id-sk (str (get-in message [:header :entity-id :perf-asmt-id]))}
+                                         (hatch/slam-all (get-in message [:paylod :entity]) :perf-asmt))))
 (defn user2comp-in [db-conn message]
   (tx-entity! db-conn :user2comp (hatch/slam-all (get-in message [:payload :entity]) :user2comp)))


treat ugens args with :array set to true as sequences

--- src/overtone/repl/debug.clj
+++ src/overtone/repl/debug.clj
@@ -76,7 +76,8 @@
                             input-specs input-specs]
                        (if (empty? input-specs)
                          res
-                         (if (ugen-sequence-mode? (:mode (first input-specs)))
+                         (if (or (ugen-sequence-mode? (:mode (first input-specs)))
+                                 (= true (:array (first input-specs))))
                            (let [arg-seq (drop (dec (count input-specs)) inputs)
                                  inputs  (drop-last (count arg-seq) inputs)]
                              (recur (assoc res (keyword (:name (first input-specs))) (vec arg-seq))


need to deploy backend first

need to deploy backend first

--- src/pc/assets.clj
+++ src/pc/assets.clj
@@ -220,8 +220,9 @@
                      :metadata {:content-length (count manifest-bytes)
                                 :content-type "application/edn"})
       (validate-manifest! (fetch-specific-manifest cdn-bucket manifest-key))
-      (log/infof "moving manifest pointer to %s" manifest-key)
-      (move-manifest-pointer cdn-bucket manifest-key)
+      ;;(log/infof "moving manifest pointer to %s" manifest-key)
+      (log/infof "skip moving manifest pointer to %s" manifest-key)
+      ;;(move-manifest-pointer cdn-bucket manifest-key)
       (log/infof "uploading sourcemap to rollbar")
       (upload-sourcemap sha1 manifest))))


hack to make server not redirect haproxy health checks

--- src/pc/server.clj
+++ src/pc/server.clj
@@ -44,7 +44,8 @@

 (defn ssl? [req]
   (or (= :https (:scheme req))
-      (= "https" (get-in req [:headers "x-forwarded-proto"]))))
+      (= "https" (get-in req [:headers "x-forwarded-proto"]))
+      (seq (get-in req [:headers "x-haproxy-server-state"]))))

 (def bucket-doc-ids (atom #{}))


Fix duration string parsing

Fix duration string parsing

--- src/popup/ygq/popup/ui.cljs
+++ src/popup/ygq/popup/ui.cljs
@@ -6,7 +6,8 @@
             [untangled.client.core :as uc]
             [untangled.client.mutations :refer [mutate]]
             [untangled.client.data-fetch :as df]
-            [cljs.spec :as s]))
+            [cljs.spec :as s]
+            [clojure.string :as str]))

 (defmethod mutate 'auth/token-received [{:keys [state]} _ {:keys [token]}]
   {:action (fn []
@@ -44,10 +45,11 @@
   (dom/span #js {:className (str "glyphicon glyphicon-" name)}))

 (defn duration-str [duration]
-  (if-let [[h m s] (some->> (re-find #"(?:(\d+)H)?(\d+)M(\d+)S$" duration)
-                            next (map #(some-> % (gstr/padNumber 2))))]
-    (cond->> (str m ":" s)
-             h (str h ":"))))
+  (if-let [[h m s] (some->> (re-find #"(?:(\d+)H)?(?:(\d+)M)(?:(\d+)S)?$" duration)
+                            next)]
+    (let [items (->> (filter some? [h (or m 0) (or s 0)])
+                     (map #(some-> % (gstr/padNumber 2))))]
+      (str/join ":" items))))

 (s/def ::duration string?)


deprecetae unsafe react lifecycle methods

--- src/rum/core.cljs
+++ src/rum/core.cljs
@@ -34,8 +34,8 @@
            vals
            (run! #(.warn js/console %)))))
   (let [init           (collect   :init mixins)             ;; state props -> state
-        will-mount     (collect [:will-mount] mixins)   ;; state -> state
-        before-render  (collect* [:unsafe/will-mount
+        before-render  (collect* [:will-mount
+                                  :unsafe/will-mount
                                   :before-render] mixins)   ;; state -> state
         render         render                               ;; state -> [dom state]
         wrap-render    (collect   :wrap-render mixins)      ;; render-fn -> render-fn
@@ -45,8 +45,8 @@
         will-remount    (collect* [:did-remount             ;; state -> state
                                    :will-remount] mixins)   ;; old-state state -> state
         should-update  (collect   :should-update mixins)    ;; old-state state -> boolean
-        will-update    (collect [:will-update] mixins)   ;; state -> state
         before-update  (collect* [:unsafe/will-update
+                                  :unsafe/will-update
                                   :before-render] mixins)   ;; state -> state
         did-update     (collect* [:did-update               ;; state -> state
                                   :after-render] mixins)    ;; state -> state
@@ -68,12 +68,6 @@
         _              (goog/inherits ctor js/React.Component)
         prototype      (gobj/get ctor "prototype")]

-    (when-not (empty? will-mount)
-      (gobj/set prototype "componentWillMount"
-                (fn []
-                  (this-as this
-                           (vswap! (state this) call-all will-mount)))))
-
     (when-not (empty? before-render)
       (gobj/set prototype "UNSAFE_componentWillMount"
                 (fn []
@@ -103,13 +97,6 @@
                            (let [old-state @(state this)
                                  new-state @(gobj/get next-state ":rum/state")]
                              (or (some #(% old-state new-state) should-update) false))))))
-
-    (when-not (empty? will-update)
-      (gobj/set prototype "componentWillUpdate"
-                (fn [_ next-state]
-                  (this-as this
-                           (let [new-state (gobj/get next-state ":rum/state")]
-                             (vswap! new-state call-all will-update))))))

     (when-not (empty? before-update)
       (gobj/set prototype "UNSAFE_componentWillUpdate"


(TK-373) Enable Diffie-Hellman cipher suites

This commit enables cipher suites that use classical and elliptic curve
ephemeral Diffie Hellman for key exchange. Per the Mozilla server side
TLS recommendations ECDHE ciphers are preferred, then EDH, and then we
fall back to the original cipher list.

--- src/puppetlabs/trapperkeeper/services/webserver/jetty9_config.clj
+++ src/puppetlabs/trapperkeeper/services/webserver/jetty9_config.clj
@@ -52,23 +52,22 @@
 ;;; their implicit defaults reflect the security issue.  The latter is far more
 ;;; risky for our downstream apps, thus it was decided that it makes sense to
 ;;; keep these overrides.
-;;;
-;;; Also note that w/rt the default list of acceptable ciphers, we're deliberately
-;;; excluding all diffie-helman ciphers due to some old JDK bugs:
-;;;
-;;; http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8014618
-;;; https://github.com/puppetlabs/puppetdb/commit/03e020dc85b83d6c83c9992ca6bd14f57e8fc91a
-;;;
-;;; These have been fixed in recent versions of the JDK, and it would be nice
-;;; to be able to add the DH ciphers back in at some point, but we can't do that
-;;; until we're certain that our minimum supported JDK versions for all of our
-;;; supported distros will contain the relevant fixes.
-;;;
 (def acceptable-ciphers
-  ["TLS_RSA_WITH_AES_256_CBC_SHA256"
+  ["TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA256"
+   "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
+   "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
+   "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
+
+   "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"
+   "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"
+   "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
+   "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
+
+   "TLS_RSA_WITH_AES_256_CBC_SHA256"
    "TLS_RSA_WITH_AES_256_CBC_SHA"
    "TLS_RSA_WITH_AES_128_CBC_SHA256"
    "TLS_RSA_WITH_AES_128_CBC_SHA"
+
    "SSL_RSA_WITH_RC4_128_SHA"
    "SSL_RSA_WITH_3DES_EDE_CBC_SHA"
    "SSL_RSA_WITH_RC4_128_MD5"])


Fix System Namespace

Fix System Namespace

--- dev/system.clj
+++ dev/system.clj
@@ -1,4 +1,5 @@
 (ns system
+  (:use plumbing.core)
   (:require [clojure.string :as str]
             [org.httpkit.server :refer [run-server]]
             [datomic.api :as d]
@@ -26,13 +27,11 @@
    :db-uri (or (env "DB_URI") (create-mem-db))
    :token-introspection-uri (env "TOKEN_INTROSPECTION_URI")
    :context-path (or (env "CONTEXT_PATH") "/")
-   :version (System/getProperty "lens.version")
+   :version (System/getProperty "lens-workbook.version")
    :port (or (some-> (env "PORT") (parse-int)) 5002)})

-(defn start [{:keys [app db-uri token-introspection-uri context-path port]
-              :as system}]
-  (let [stop-fn (run-server (app db-uri token-introspection-uri context-path)
-                            {:port port})]
+(defnk start [app port & more :as system]
+  (let [stop-fn (run-server (app more) {:port port})]
     (assoc system :stop-fn stop-fn)))

 (defn stop [{:keys [stop-fn] :as system}]


added make-into-tagspaces aspect to :vector type

--- src/push/type/item/vector.clj
+++ src/push/type/item/vector.clj
@@ -41,6 +41,7 @@
       aspects/make-collectible
       aspects/make-cycling
       aspects/make-equatable
+      aspects/make-into-tagspaces
       aspects/make-movable
       aspects/make-printable
       aspects/make-quotable


Template is for a function.

Template is for a function.

--- exercises/proverb/src/proverb.clj
+++ exercises/proverb/src/proverb.clj
@@ -1,3 +1,5 @@
 (ns proverb)

-(def proverb "")
+(defn proverb [] ;; <- arglist goes here
+    ;; your code goes here
+)


Require edge.system on-demand

Require edge.system on-demand

This significantly speeds up tasks such as `boot repl`

--- build.boot
+++ build.boot
@@ -83,8 +83,7 @@
          '[adzerk.boot-reload :refer [reload]]
          '[deraen.boot-sass :refer [sass]]
          '[com.stuartsierra.component :as component]
-         'clojure.tools.namespace.repl
-         '[edge.system :refer [new-system]])
+         'clojure.tools.namespace.repl)

 (def repl-port 5600)

@@ -152,12 +151,13 @@

 (deftask run-system
   [p profile VAL str "Profile to start system with"]
-  (with-post-wrap fileset
-    (println "Running system with profile" profile)
-    (let [system (new-system profile)]
-      (component/start system)
-      (intern 'user 'system system)
-      (assoc fileset :system system))))
+  (require 'edge.system)
+  (let [new-system (resolve 'edge.system/new-system)]
+    (with-post-wrap fileset
+      (let [system (new-system profile)]
+        (component/start system)
+        (intern 'user 'system system)
+        (assoc fileset :system system)))))

 (deftask run [p profile VAL kw "Profile"]
   (comp


Add task to push without gpg

Add task to push without gpg

--- build.boot
+++ build.boot
@@ -4,11 +4,11 @@
                   [adzerk/bootlaces "0.1.13"   :scope "test"]])

 (require
-  '[adzerk.bootlaces :refer :all]) ;; tasks: build-jar push-snapshot push-release
+  '[adzerk.bootlaces :as deploy])

 (def +version+ "1.0.0")

-(bootlaces! +version+)
+(deploy/bootlaces! +version+)

 (task-options!
   pom {:project     'afrey/boot-asset-fingerprint
@@ -21,4 +21,14 @@
 (deftask dev []
   (comp
     (watch)
-    (build-jar)))
+    (deploy/build-jar)))
+
+(deftask push-release []
+  (comp
+    (deploy/build-jar)
+    (#'deploy/collect-clojars-credentials)
+    (push
+      :tag            true
+      :gpg-sign       false
+      :ensure-release true
+      :repo           "deploy-clojars")))


0.1.6 -- fix issue where setting ip removes port config

--- build.boot
+++ build.boot
@@ -5,7 +5,7 @@

 (require '[tailrecursion.boot-useful :refer :all])

-(def +version+ "0.1.6")
+(def +version+ "0.1.7")

 (useful! +version+)


Use httpkit 2.2.0 to fix memory leak with websockets (https://github.com/http-kit/http-kit/issues/165)

--- backend/project.clj
+++ backend/project.clj
@@ -6,7 +6,7 @@
   :dependencies [[org.clojure/clojure "1.7.0"]
                  [lambdacd "0.9.3"]
                  [compojure "1.5.0"]
-                 [http-kit "2.1.18"]
+                 [http-kit "2.2.0"]
                  [org.clojure/data.json "0.2.6"]
                  [org.slf4j/slf4j-simple "1.7.22"]
                  [trptcolin/versioneer "0.2.0"]]


only accepting JSON

only accepting JSON

--- frontend/utils.cljs
+++ frontend/utils.cljs
@@ -137,7 +137,7 @@
     (ajax/ajax-request url method
                        (ajax/transform-opts
                         {:format (json-response-format {:keywords? keywords? :url url :method method})
-                         :response-format response-format
+                         :response-format :json
                          :keywords? keywords?
                          :params params
                          :headers (merge {:Accept "application/json"}


Redirect "/" to current issue

Redirect "/" to current issue

--- src/catalog/web/views.clj
+++ src/catalog/web/views.clj
@@ -2,6 +2,7 @@
   "Views for web application"
   (:require [catalog
              [db :as db]
+             [issue :as issue]
              [validation :as validation]
              [vubis :as vubis]]
             [catalog.layout
@@ -11,6 +12,7 @@
              [obi :as layout.obi]]
             [catalog.web.layout :as layout]
             [cemerick.friend :as friend]
+            [clj-time.core :as time.core]
             [clojure
              [edn :as edn]
              [string :as string]]
@@ -35,7 +37,9 @@

 (defn home
   ([request]
-   (home request 2016 3)) ;; FIXME: hard coded for now
+   (let [date (time.core/today)
+         [year issue] (issue/issue-for date)]
+     (response/redirect (format "/%s/%s" year issue))))
   ([request year issue]
    (let [identity (friend/identity request)]
      (layout/common


Move the transducer of cat-maybes out of function.

As suggested by @dialelo.

--- src/cats/monad/maybe.cljc
+++ src/cats/monad/maybe.cljc
@@ -304,14 +304,17 @@
     (lazy-seq [])
     (lazy-seq [(p/extract m)])))

+(def ^{:private true :no-doc true}
+  +extract-just-xform+
+  (comp
+   (filter just?)
+   (map p/extract)))
+
 (defn cat-maybes
   "Given a collection of maybes, return a sequence of the values
   that the just's contain."
   [coll]
-  (let [xform (comp
-               (filter just?)
-               (map p/extract))]
-    (sequence xform coll)))
+  (sequence +extract-just-xform+ coll))

 (defn map-maybe
   "Given a maybe-returning function and a collection, map the function over


Don't show dests in board editor

Don't show dests in board editor

--- src/chessground/ctrl.cljs
+++ src/chessground/ctrl.cljs
@@ -21,7 +21,8 @@
     [new-state
      (fn [$app chans]
        (show/selected $app orig)
-       (show/dests $app (data/dests-of state orig)))]))
+       (when (not (:free (:movable state)))
+         (show/dests $app (data/dests-of state orig))))]))

 (defn move-piece [state [orig dest]]
   (or (when (data/can-move? state orig dest)


Unshow dests when dropping piece off board

--- src/chessground/ctrl.cljs
+++ src/chessground/ctrl.cljs
@@ -120,6 +120,7 @@
       [new-state
        (fn [root chans]
          (show/selected root nil)
+         (show/dests root nil)
          (show/un-move root key))])))

 (defn clear [state]


Fleshed out sketch of chicken coop code

Fleshed out sketch of chicken coop code

--- src/chicken_coop/core.clj
+++ src/chicken_coop/core.clj
@@ -6,7 +6,127 @@
             [chicken-coop.ain :as ain]))

+(defn on? [gp]
+  (= (:on (gpio/read! gp))))
+
+
+(defn off? [gp]
+  (= (:off (gpio/read! gp))))
+
+; Helper functions so I can keep track of whether doors are closed or open
+(def closed? off?)
+(def open? on?)
+
+
+(defprotocol HBridgeable
+  (forward! [this])
+  (reverse! [this])
+  (stop! [this]))
+
+
+(defn writes! [pins bit]
+  (doseq [p pins]
+    (gpio/write! p bit)))
+
+
+(defrecord HBridge [+for -for +rev -rev]
+  HBridgeable
+  (forward! [_]
+    ; Reverse circuit off
+    (writes! [+rev -rev] :off)
+    ; Wait a tad to prevent short
+    (Thread/sleep 10)
+    ; Turn forward circuit on
+    (writes! [+for -for] :on))
+  (reverse! [_]
+    ; similarly as forward! ...
+    (writes! [+for -for] :off)
+    (Thread/sleep 10)
+    (writes! [+rev -rev] :on))
+  (stop! [_]
+    (writes! [+for -for +rev -rev] :off)))
+
+
+(defn h-bridge [[+for-pin -for-pin +rev-pin -rev-pin :as pins]]
+  (apply #(HBridge. %1 %2 %3 %4)
+         (map #(gpio/gpio (first %) (second %) :out) pins)))
+
+
+(defmacro wait-till [test body]
+  `(loop []
+     (if ~test
+       (do
+         ~@body)
+       (recur))))
+
+
+(defn close-door! [hb floor-io]
+  (forward! hb)
+  (wait-till (closed? floor-io)
+    (stop! hb)))
+
+
+(defn open-door! [hb roof-io]
+  (reverse! hb)
+  (wait-till (closed? roof-io)
+    (stop! hb)))
+
+
+(defn time-sm [state day-fn! night-fn!]
+  (let [dusk 0.3
+        dawn 0.4]
+    {:state state
+     :trans
+        {:day
+            (fn [brightness]
+              (if (< brightness dusk)
+                (do
+                  ; state side effects
+                  (night-fn!)
+                  :night)
+                :day))
+         :night
+            (fn [brightness]
+              (if (> brightness dawn)
+                (do
+                  ; state side effects
+                  (day-fn!)
+                  :day)
+                :night))}}))
+
+
+(defn trans-sm! [sm m]
+  (assoc sm :state
+    (((:trans sm) (:state sm)) m)))
+
+
+(defn init-state!
+  [floor-io roof-io light-ain]
+  (cond
+    (closed? floor-io) :night
+    (closed? roof-io) :day
+    (> (ain/read! light-ain) 0.35) :day
+    :else :night))
+
+
+(defn check [] (println "compiled!"))
+
+
 (defn -main []
+  (let [_ 33
+        floor-io (gpio/gpio _ _ _)
+        roof-io (gpio/gpio _ _ _)
+        light-ain (ain/ain _)
+        hb (h-bridge [:P8 _] [:P8 _] [:P8 _] [:P8 _])
+        timer (time-sm
+                (init-state! floor-io roof-io light-ain)
+                (partial close-door! hb roof-io)
+                (partial open-door! hb roof-io))]
+    (loop [time-sm time-sm]
+      (recur (trans-sm! timer (ain/read! light-ain))))))
+
+
+(defn play []
   (println "ready to initialize")
   (let [g (gpio/gpio :P8 11 :low)
         a (ain/ain 33)]


CLJS-447: Throw exception if multiple namespaces are required with the same alias

Track aliases in parse 'ns. Throw on duplicate name.

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -603,6 +603,7 @@
                     s))
                 #{} args)
         deps (atom #{})
+        aliases (atom #{})
         valid-forms (atom #{:use :use-macros :require :require-macros :import})
         error-msg (fn [spec msg] (str msg "; offending spec: " (pr-str spec)))
         parse-require-spec (fn parse-require-spec [macros? spec]
@@ -624,6 +625,10 @@
                                (let [[lib & opts] spec
                                      {alias :as referred :refer :or {alias lib}} (apply hash-map opts)
                                      [rk uk] (if macros? [:require-macros :use-macros] [:require :use])]
+                                 (when alias
+                                   (assert (not (contains? @aliases alias))
+                                           (error-msg spec ":as alias must be unique"))
+                                   (swap! aliases conj alias))
                                  (assert (or (symbol? alias) (nil? alias))
                                          (error-msg spec ":as must be followed by a symbol in :require / :require-macros"))
                                  (assert (or (and (sequential? referred) (every? symbol? referred))