add dwell time

add dwell time

--- modules/src/samsara_builtin_modules/sessionize.clj
+++ modules/src/samsara_builtin_modules/sessionize.clj
@@ -62,15 +62,25 @@
     (let [stop
           (when prev-event
             (-> (cleanup-prev-event prev-event)
-                (inject-as :eventName (str *session-event-basename* ".stopped"))))
+                (inject-as :eventName (str *session-event-basename* ".stopped"))
+                (inject-as :inferred true)
+                (dissoc :isSessionStart)))
           start
           (-> (cleanup-prev-event event)
-              (inject-as :eventName (str *session-event-basename* ".started")))]
-      (println "stop:" stop)
-      (println "start:" start)
+              (inject-as :eventName (str *session-event-basename* ".started"))
+              (inject-as :inferred true)
+              (dissoc :isSessionStart))]
       (if stop
         [stop start]
         [start]))))
+
+
+
+(defenrich calculate-dwell-time
+  [{:keys [isSessionStart ::prev-event timestamp] :as event}]
+  (inject-as event :dwellTime
+             (when (and prev-event (not isSessionStart))
+               (- timestamp (:timestamp prev-event)))))

@@ -79,6 +89,7 @@
    add-sessionId
    identify-session-start
    emit-session-start-and-stop
+   calculate-dwell-time
    cleanup-prev-event
    session-boundaries-correlation))

@@ -90,4 +101,7 @@

   (def proc (moebius sessionize-web-requests))

-  (proc (kv/make-in-memory-kvstore) events))
+  (second
+   (proc (kv/make-in-memory-kvstore) events) )
+
+  )


Simplify test.

Simplify test.

--- test/onyx/generative/acking_daemon_gen_test.clj
+++ test/onyx/generative/acking_daemon_gen_test.clj
@@ -1,16 +1,13 @@
 (ns onyx.generative.acking-daemon-gen-test
-  (:require [clojure.core.async :refer [chan dropping-buffer]]
+  (:require [clojure.core.async :refer [chan]]
             [clojure.test :refer :all]
             [clojure.test :refer [is]]
             [clojure.test.check.generators :as gen]
             [stateful-check.core :refer [specification-correct?]]
-            [onyx.messaging.acking-daemon :as a]))
+            [onyx.messaging.acking-daemon :as a])
+  (:import [java.util UUID]))

 (def max-state-size 10000)
-
-(def gen-uuid
-  (gen/fmap (fn [[a b]] (java.util.UUID. a b))
-            (gen/resize Long/MAX_VALUE (gen/tuple gen/int gen/int))))

 (def new-segment-specification
   ;; Disallow the acking daemon state to grow too large by not
@@ -26,11 +23,11 @@
      (let [message-ids (keys (:model-state state))
            new-msg-id (fn [v] (not (some #{v} message-ids)))]
        [(:real-state state)
-        (gen/return (chan (dropping-buffer 1)))
-        (gen/hash-map :id (gen/such-that new-msg-id gen-uuid)
-                      :completion-id gen-uuid
-                      :ack-val (gen/such-that #(not= 0 %)
-                                              (gen/resize Long/MAX_VALUE gen/int)))]))
+        (gen/return (chan 1))
+        (gen/hash-map
+         :id (gen/no-shrink (gen/return (UUID/randomUUID)))
+         :completion-id (gen/no-shrink (gen/return (UUID/randomUUID)))
+         :ack-val (gen/no-shrink (gen/return (a/gen-ack-value))))]))

    :real/command #'a/ack-segment

@@ -64,23 +61,14 @@
      (let [message-ids (keys (:model-state state))
            id-gen (gen/elements message-ids)]
        [(:real-state state)
-        (gen/return (chan (dropping-buffer 1)))
-        (gen/hash-map :id id-gen
-                      :ack-val
-                      (gen/bind
-                       id-gen
-                       (fn [id]
-                         (gen/such-that
-                          (fn [ack-val]
-                            (let [current-ack-val (get-in state [:model-state id :ack-val])]
-                              (and (not= current-ack-val ack-val)
-                                   (not= 0 ack-val)
-                                   (not= 0 (bit-xor ack-val current-ack-val)))))
-                          (gen/resize Long/MAX_VALUE gen/int))))
-                      :completion-id
-                      (gen/bind
-                       id-gen
-                       #(gen/return (get-in state [:model-state % :completion-id]))))]))
+        (gen/return (chan 1))
+        (gen/hash-map
+         :id id-gen
+         :ack-val (gen/return (a/gen-ack-value))
+         :completion-id
+         (gen/bind
+          id-gen
+          #(gen/return (get-in state [:model-state % :completion-id]))))]))

    ;; Notice this is the same command as the new-segment
    ;; specification. It works for both types of interactions.


Support JSON pretty printing for ring.expose/serve-metrics


Update data source key used in simple text widget

--- src/cljs/dashboard_clj/widgets/simple_text.cljs
+++ src/cljs/dashboard_clj/widgets/simple_text.cljs
@@ -8,7 +8,7 @@
    [:span {:class "title"} (:title w)]
    [:div {:class "data"}
     [:span
-     (get-in @data [:value]) (:text w)]]
+     (get-in @data [:data]) (:text w)]]
    ])


Tune cljs dependency warning

Tune cljs dependency warning

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -22,7 +22,7 @@
       ; org.clojure/clojurescript in project (non-transitive) deps - do nothing
       cljs-dep?    nil
       ; cljs.core on classpath, org.clojure/clojurescript not in project deps
-      cljs-exists? (do (warn "WARNING: No ClojureScript dependency in project dependencies but ClojureScript in classpath\n") nil)
+      cljs-exists? (do (warn "WARNING: No ClojureScript in project dependencies but ClojureScript was found in classpath. Adding direct dependency is adviced.\n") nil)
       ; no cljs on classpath, no project dep, add cljs dep to pod
       :else        ['org.clojure/clojurescript cljs-version])))


Make piece a fn rather than data so that we don't hold the head of a lazy sequence.

--- src/african_polyphony_and_polyrhythm/talk.clj
+++ src/african_polyphony_and_polyrhythm/talk.clj
@@ -127,8 +127,7 @@
          (canon #(->> % (take 32) (then (rhythm [1/8])) ostinato (all :part :child))))))

 (comment
-  (->> (clapping-music)
-       live/play))
+  (live/play (clapping-music)))

@@ -260,21 +259,19 @@
                    (-> pitch (/ 18) dec -))]
     (assoc note :pan position)))

-(def ndereje-balendoro ; p 343
+(defn ndereje-balendoro [] ; p 343
   (->> [tete ta ha tulule bongo
         (big tete) (big ta) (big ha) (big tulule) (big bongo)
         (big (big tete)) (big (big ta)) (big (big ha)) (big (big tulule)) (big (big bongo))
         (big (big (big tete))) (big (big (big ta))) (big (big (big ha)))]
        (map rand-variations)
-       (introduce-after 4)))
-
-(comment
-  (->>
-    ndereje-balendoro
-    (map pan)
-    (where :pitch (comp midi->hz A central-african-scale))
-    (tempo (bpm 120))
-    live/play))
+       (introduce-after 4)
+       (map pan)
+       (where :pitch (comp midi->hz A central-african-scale))
+       (tempo (bpm 120))))
+
+(comment
+  (live/play (ndereje-balendoro)))


default train type feature

default train type feature

--- src/clojure/zensols/model/eval_classifier.clj
+++ src/clojure/zensols/model/eval_classifier.clj
@@ -20,6 +20,13 @@
   "The default number of folds to use during cross fold
   validation (see [[cmpile-results]])."
   10)
+
+(def ^:dynamic *default-set-type*
+  "The default type of test, which is one of:
+
+      * `:cross-validation`: run a N fold cross validation (default)
+      * `:test-train`: train the classifier and then evaluate"
+  :cross-validation)

 (defn print-model-config
   "Pretty print the model configuation set with [[with-model-conf]]."
@@ -178,11 +185,9 @@

   Keys
   ----
-  * **:test-type** the type of test to run; one of:
-      * `:cross-validation`: run a N fold cross validation (default)
-      * `:test-train`: train the classifier and then evaluate"
+  * **:test-type** the type of test to run (see [[*default-set-type*]])"
   [classifier-sets feature-set-key &
-   {:keys [test-type] :or {test-type :cross-validation}}]
+   {:keys [test-type] :or {test-type *default-set-type*}}]
   (let [test-fn (case test-type
                   :cross-validation cross-validate-results
                   :test-train test-train-results)
@@ -207,13 +212,11 @@
   Keys
   ----
   * **:only-stats?** if `true` only return statistic data
-  * **:test-type** the type of test to run; one of:
-      * `:cross-validation`: run a N fold cross validation (default)
-      * `:test-train`: train the classifier and then evaluate"
+  * **:test-type** the type of test to run (see [[*default-set-type*]])"
   [classifier-sets feature-set-key &
    {:keys [only-stats? test-type]
     :or {only-stats? true
-         test-type :cross-validation}}]
+         test-type *default-set-type*}}]
   (let [res (compile-results classifier-sets feature-set-key)]
     (log/debugf "terse results count %d" (count res))
     (map (fn [elt]


Use createClass compatibility function

Use createClass compatibility function

--- src/breeze/quiescent.clj
+++ src/breeze/quiescent.clj
@@ -48,7 +48,7 @@
           `(cljs.core/specify! ~o ~@proto+specs)))))

 (defmacro createClass [& specs]
-  `(js/React.createClass (createMixin ~@specs)))
+  `(js/createClass (createMixin ~@specs)))

 (defmacro defclass [name docstr & specs]
   (assert (symbol? name) "Must supply a symbol for name (as with def).")


Fix unexpected exception on bytes/equals? predicate.

When zero-length arrays are compared.

--- src/buddy/core/bytes.clj
+++ src/buddy/core/bytes.clj
@@ -60,7 +60,7 @@
   [a b]
   (let [a (map int a), b (map int b)]
     (if (and a b (= (count a) (count b)))
-      (zero? (reduce bit-or (map bit-xor a b)))
+      (zero? (reduce bit-or 0 (map bit-xor a b)))
       false)))

 (defn concat


fixed this non-backwards compatible fn call

--- src/midje/checkers/simple.clj
+++ src/midje/checkers/simple.clj
@@ -61,7 +61,7 @@
   "Combines multiple checkers into one checker that passes
    when all component checkers pass."
   [& checkers]
-  (as-checker (apply every-pred checkers)))
+  (as-checker (apply every-pred-m checkers)))

 (defn some-checker
   "Combines multiple checkers into one checker that passes


(parse) now has metadata :constants?, indicating if bools are in formula

--- src/mpa/cst/parser/parser.clj
+++ src/mpa/cst/parser/parser.clj
@@ -7,15 +7,15 @@
 (MpaParser. (StringReader. ""))

 (defn- cst2list
-  [cst]
+  [cst *const?*]
   (case (.jjtGetNumChildren cst)
     0 (case (.getLexeme cst) ; Boolean | Atom
-        "TRUE" 'true
-        "FALSE" 'false
+        "TRUE" (do (reset! *const?* true) 'true)
+        "FALSE" (do (reset! *const?* true) 'false)
         (symbol (.getLexeme cst)))
     1 (if (= (class cst) mpa.cst.parser.MpaNotExpr) ; NOT | hierarchic descent
-        (list 'not (cst2list (.jjtGetChild cst 0)))
-        (cst2list (.jjtGetChild cst 0)))
+        (list 'not (cst2list (.jjtGetChild cst 0) *const?*))
+        (cst2list (.jjtGetChild cst 0) *const?*))
     2 (let [op-nr (.getOp cst)
             AND (MpaParser/AND)
 						NAND (MpaParser/NAND)
@@ -38,10 +38,13 @@
                  (= op-nr NIMPL) 'nimpl
                  (= op-nr IFF) 'equiv
                  (= op-nr XOR) 'xor)]
-        (list op (cst2list (.jjtGetChild cst 0)) (cst2list (.jjtGetChild cst 1))))))
+        (list op (cst2list (.jjtGetChild cst 0) *const?*) (cst2list (.jjtGetChild cst 1) *const?*)))))

 (defn javaCCparse
   [formula]
   (MpaParser/ReInit (StringReader. formula))
-  (let [cst (MpaParser/Start)]
-    (cst2list cst)))
+  (let [cst (MpaParser/Start)
+        *const?* (atom false)
+        parsed (cst2list cst *const?*)]
+    (with-meta parsed {:constants? @*const?*})))
+


gruff

gruff

--- src/nodecljs/server/core.cljs
+++ src/nodecljs/server/core.cljs
@@ -28,7 +28,7 @@

 (defn server [handler port success]
   (doto (express)
-    (.get "/" jokes-handler)
+    (.get "/" handler)
     (.use (.static express "../resources/public"))
     (.listen port success)))


run the migration for the access entities also

--- src/pc/datomic/migrations.clj
+++ src/pc/datomic/migrations.clj
@@ -59,15 +59,17 @@
   ;; assuming that only entities with document-ids need one. May
   ;; require another migration later if that's false.
   (let [db (d/db conn)]
-    (dorun (pmap (fn [datoms]
-                   @(d/transact-async conn
-                                      (conj
-                                       (for [d datoms]
-                                         [:db/add (:e d) :frontend/id (UUID. (:v d) (:e d))])
-                                       {:db/id (d/tempid :db.part/tx)
-                                        :transaction/source :transaction.source/migration
-                                        :migration :migration/add-frontend-ids})))
-                 (partition-all 100 (d/datoms db :aevt :document/id))))))
+    (doseq [attr [:document/id :permission/document :access-grant/document :access-request/document]]
+      (dorun (pmap (fn [datoms]
+                     @(d/transact-async conn
+                                        (conj
+                                         (for [d datoms]
+                                           [:db/add (:e d) :frontend/id (UUID. (:v d) (:e d))])
+                                         {:db/id (d/tempid :db.part/tx)
+                                          :transaction/source :transaction.source/migration
+                                          :migration :migration/add-frontend-ids})))
+                   (partition-all 100 (remove #(:frontend/id (d/entity db (:e %)))
+                                              (d/datoms db :aevt attr))))))))

 (def migrations
   "Array-map of migrations, the migration version is the key in the map.


Update reason string to be more useful (#400)

Mesos command executor failed is not transparent to users

--- scheduler/src/cook/mesos/schema.clj
+++ scheduler/src/cook/mesos/schema.clj
@@ -1140,7 +1140,7 @@
     :reason/mesos-reason :reason-executor-terminated}
    {:db/id (d/tempid :db.part/user)
     :reason/code 99003
-    :reason/string "Mesos command executor failed"
+    :reason/string "Command exited non-zero"
     :reason/name :mesos-command-executor-failed
     :reason/mea-culpa? false
     :reason/mesos-reason :reason-command-executor-failed}])


add conevrt value matching multimethod

add conevrt value matching multimethod

--- src/ca_recipe/recipe.clj
+++ src/ca_recipe/recipe.clj
@@ -34,3 +34,21 @@
 (defmethod cost Ingredient [ingredient store]
   (cost-of store ingredient))

+(defmulti convert
+  "Convert quality from unit1 to unit2, matching on [unit1 unit2]"
+  (fn [unit1 unit2 quality] [unit1 unit]))
+
+(defmethod convert [:lb :oz] [_ _ lb] (* lb 16))
+
+(defmethod convert [:oz :lb] [_ _ oz] (/ oz 16))
+
+(defmethod convert :default [u1 u2 q]
+  (if (= u1 u2)
+    q
+    (asset false (str "Unknown unit conversion from " u1 " to " u2))))
+
+(defn ingredient+
+  "Add two ingredients into a single ingredient, combining their
+  quantities with unit conversion if necessary."
+  [{q1 :quantity u1 :unit :as i1} {q2 :quantity u2 :unit}]
+  (assoc i1 :quantity (+ q1 (convert u2 u1 q2))))


only message colum counts

only message colum counts

--- src/celestial/common.clj
+++ src/celestial/common.clj
@@ -79,7 +79,7 @@
    :kibana3
       "query=tid:~{tid}&fields=@timestamp,message,tid,"
    :kibana4
-      "query:(query_string:(analyze_wildcard:!t,query:'tid:~{tid}')),columns:!('@timestamp',message,tid)"
+      "query:(query_string:(analyze_wildcard:!t,query:'tid:~{tid}')),columns:!(message)"
    }
   )


localhost

localhost

--- uberjar/src/dda/pallet/dda_managed_ide/main.clj
+++ uberjar/src/dda/pallet/dda_managed_ide/main.clj
@@ -54,12 +54,17 @@
        provisioning-user)
      :summarize-session true)))

+
+(def localhost
+  {:existing [{:node-name "test-ide1"
+               :node-ip "127.0.0.1"}]})
+
 (def cli-options
   [["-h" "--help"]
    ["-s" "--server-test"]
    ["-c" "--configure"]
    ["-t" "--targets TARGETS.edn" "edn file containing the targets to install on."
-    :default "targets.edn"]])
+    :default localhost]])

 (defn usage [options-summary]
   (str/join
@@ -84,6 +89,7 @@
   (println msg)
   (System/exit status))

+
 (defn -main [& args]
   (let [{:keys [options arguments errors summary help]} (cli/parse-opts args cli-options)]
     (cond
@@ -92,15 +98,16 @@
       (not= (count arguments) 1) (exit 1 (usage summary))
       (:server-test options) (execute-server-test
                                         (app/load-domain (first arguments))
-                                        (app/load-targets (:targets options)))
+                                        (if (= (options :targets) localhost)
+                                          localhost
+                                          (app/load-targets (:targets options))))
       (:configure options) (execute-configure
                              (app/load-domain (first arguments))
-                             (app/load-targets (:targets options)))
+                             (if (= (options :targets) localhost)
+                               localhost
+                               (app/load-targets (:targets options))))
       :default (execute-install
                  (app/load-domain (first arguments))
-                 (app/load-targets (:targets options))))))
-
-(defn test [& args]
-  (let [{:keys [options arguments errors summary help]} (cli/parse-opts args cli-options)]
-    (if (contains? options :targets)
-      (:targets options) "false")))
+                 (if (= (options :targets) localhost)
+                   localhost
+                   (app/load-targets (:targets options)))))))


make clj slightly neater

make clj slightly neater

--- clojure/src/sieve/core.clj
+++ clojure/src/sieve/core.clj
@@ -3,20 +3,17 @@

 ; check if n is prime, given all primes <= n
 (defn isprime [n ps]
-  (cond
-    (empty? ps) true
-    (= 0 (mod n (first ps))) false
-    true (recur n (rest ps))))
+  (not-any? #(zero? (mod n %)) ps))

 ; find all primes up to limit
 (defn primes
+  ([limit] (primes limit 2 (sorted-set)))
   ([limit n ps] (cond
     (> n limit) ps
     (isprime n ps) (recur limit (inc n) (conj ps n))
-    true (recur limit (inc n) ps)))
-  ([limit] (primes limit 2 (sorted-set))))
+    true (recur limit (inc n) ps))))

 (defn -main
-  "I don't do a whole lot ... yet."
+  "Count the number of primes"
   [& args]
   (println (count (primes 100000))))


remove removed ns

remove removed ns

--- server/src/gratefulplace/server.clj
+++ server/src/gratefulplace/server.clj
@@ -1,7 +1,6 @@
 (ns gratefulplace.server
   (:gen-class)
-  (:require [gratefulplace.db.manage :as db]
-            [compojure.core :as compojure]
+  (:require [compojure.core :as compojure]
             [rabble.ring-app :as ring-app]
             [rabble.middleware.routes :as routes]
             [ring.adapter.jetty :refer (run-jetty)]))


Sort JavaScript files in dependency order once, just before advanced compilation

--- src/clj/cljs/closure.clj
+++ src/clj/cljs/closure.clj
@@ -347,12 +347,11 @@

 (defn compile-dir
   "Recursively compile all cljs files under the given source
-  directory. Return a list of JavaScriptFiles in dependency order."
+  directory. Return a list of JavaScriptFiles."
   [^File src-dir opts]
   (let [out-dir (output-directory opts)]
-    (dependency-order
-     (map compiled-file
-          (comp/compile-root src-dir out-dir)))))
+    (map compiled-file
+         (comp/compile-root src-dir out-dir))))

 (defn path-from-jarfile
   "Given the URL of a file within a jar, return the path of the file
@@ -514,8 +513,8 @@

 (defn js-dependencies
   "Given a sequence of Closure namespace strings, return the list of
-  all dependencies in dependency order. The returned list includes all
-  Google and third-party library dependencies.
+  all dependencies. The returned list includes all Google and
+  third-party library dependencies.

   Third-party libraries are configured using the :libs option where
   the value is a list of directories containing third-party
@@ -531,7 +530,7 @@
           (recur (into (rest requires) new-req)
                  (into visited new-req)
                  (conj deps node)))
-        (cons (get index "goog/base.js") (dependency-order deps))))))
+        (remove nil? deps)))))

 (comment
   ;; find dependencies
@@ -549,11 +548,10 @@

 (defn cljs-dependencies
   "Given a list of all required namespaces, return a list of
-  IJavaScripts which are the cljs dependencies in dependency
-  order. The returned list will not only include the explicitly
-  required files but any transitive depedencies as well. JavaScript
-  files will be compiled to the working directory if they do not
-  already exist.
+  IJavaScripts which are the cljs dependencies. The returned list will
+  not only include the explicitly required files but any transitive
+  depedencies as well. JavaScript files will be compiled to the
+  working directory if they do not already exist.

   Only load dependencies from the classpath."
   [opts requires]
@@ -574,7 +572,7 @@
             (recur (into (rest required-files) new-req)
                    (into visited new-req)
                    (conj js-deps js)))
-          (dependency-order js-deps))))))
+          (remove nil? js-deps))))))

 (comment
   ;; only get cljs deps
@@ -863,7 +861,9 @@
                      [(-compile (io/resource "cljs/nodejscli.cljs") all-opts)]))
         js-sources (if (coll? compiled)
                      (apply add-dependencies all-opts compiled)
-                     (add-dependencies all-opts compiled))]
+                     (add-dependencies all-opts compiled))
+        js-sources (cons (javascript-file nil (io/resource "goog/base.js") ["goog"] nil)
+                         (dependency-order js-sources))]
     (if (:optimizations all-opts)
       (->> js-sources
            (apply optimize all-opts)


The hiding of the banners isn't working properly and I'm just too tired ...

--- src/cljs/kenny/core.cljs
+++ src/cljs/kenny/core.cljs
@@ -546,12 +546,11 @@
        om/IRender
        (render [_]
          (dom/div nil
-                  (when-not (get-in app [:design-game])
-                    (when (>= 0 (get-in app [:hero :life]))
-                      (dom/h1 #js {:className "banner lost"} "FAIL!"))
+                  (when (>= 0 (get-in app [:hero :life]))
+                    (dom/h1 #js {:className "banner lost"} "FAIL!"))
                     (when (get-in app [:hero :game-won])
                       (dom/h1 #js {:className "banner won"} "YOU DID IT!")
-                      ))
+                      )
                   (om/build status-bar app)
                   (dom/div (if (get-in app [:design-game]) nil (add-event-listeners app))
                            (om/build hero app)


Use Langohr 1.4.x

Use Langohr 1.4.x

--- clojure/project.clj
+++ clojure/project.clj
@@ -4,4 +4,4 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure     "1.5.1"]
-                 [com.novemberain/langohr "1.3.0"]])
+                 [com.novemberain/langohr "1.4.1"]])


No longer using fcase.

No longer using fcase.

--- src/ring/adapter/httpcore.clj
+++ src/ring/adapter/httpcore.clj
@@ -14,7 +14,7 @@
              InterruptedIOException)
            (java.net URI ServerSocket)
            (java.util.concurrent Executors Executor ThreadFactory))
-  (:use (clojure.contrib fcase except)))
+  (:use (clojure.contrib except)))

 (defmacro #^{:private true} -?>
  ([form] form)


consistently set z-index for the hud

consistently set z-index for the hud

--- src/main/shadow/cljs/devtools/client/hud.cljs
+++ src/main/shadow/cljs/devtools/client/hud.cljs
@@ -97,7 +97,8 @@
            :style {:position "absolute"
                    :pointer-events "none"
                    :left "0px"
-                   :bottom "20px"}}
+                   :bottom "20px"
+                   :z-index "10000"}}
      [:div {:style {:background "#eee"
                     :border-top-right-radius "40px"
                     :border-bottom-right-radius "40px"
@@ -234,7 +235,7 @@
               :color "#000"
               :background-color "#fff"
               :border "5px solid red"
-              :z-index "100"
+              :z-index "10000"
               :padding "20px"
               :overflow "auto"
               :font-family "monospace"
@@ -254,7 +255,8 @@
            :style {:position "absolute"
                    :pointer-events "none"
                    :left "0px"
-                   :bottom "20px"}}
+                   :bottom "20px"
+                   :z-index "10000"}}
      [:div {:style {:background "#c00"
                     :border-top-right-radius "40px"
                     :border-bottom-right-radius "40px"


remove done todo

remove done todo

--- src/org/zalando/stups/friboo/system/metrics.clj
+++ src/org/zalando/stups/friboo/system/metrics.clj
@@ -48,7 +48,6 @@
       (let [start    (System/currentTimeMillis)
             response (next-handler request)
             status   (:status response)
-            ;; TODO replace "zmon" with configuration value
             prefix   (config/require-config configuration :metrics-prefix)
             timer    (tmr/timer metrics-registry [prefix "response" (swagger1st-request2string request status)])]
         (.update timer (- (System/currentTimeMillis) start) (TimeUnit/MILLISECONDS))


squash! Mongo Relative Dates :scream_cat:

--- src/metabase/driver/mongo/query_processor.clj
+++ src/metabase/driver/mongo/query_processor.clj
@@ -11,7 +11,8 @@
                     [db :as mdb]
                     [operators :refer :all]
                     [query :refer :all])
-            [metabase.db :refer :all]
+            (metabase [config :as config]
+                      [db :refer :all])
             [metabase.driver.query-processor :as qp]
             (metabase.driver.query-processor [annotate :as annotate]
                                              [interface :refer [qualified-name-components map->DateTimeField map->DateTimeValue]])
@@ -411,6 +412,6 @@
       (log-monger-form generated-pipeline)
       (->> (with-mongo-connection [_ database]
              (mc/aggregate *mongo-connection* source-table-name generated-pipeline
-                           :allow-disk-use true))
+                           :allow-disk-use (not (config/is-test?))))
            unescape-names
            unstringify-dates))))


Little helper function

Little helper function

--- src/midje/parsing/2_to_lexical_maps/fakes.clj
+++ src/midje/parsing/2_to_lexical_maps/fakes.clj
@@ -68,6 +68,10 @@
           (apply error/report-error call-form (disallowed-function-failure-lines actual-var))))
   [call-form fnref args arrow result overrides])

+(defn assert-valid! [form]
+  (assert-right-shape! form)
+  (valid-pieces form))
+
 (defn to-lexical-map-form [a-list]
   (assert-right-shape! a-list)
   (apply lexical-maps/fake (valid-pieces a-list)))


Fix semantics of request-contacts-by-address

--- src/status_im/ui/screens/contacts/events.cljs
+++ src/status_im/ui/screens/contacts/events.cljs
@@ -139,12 +139,12 @@
                    (dispatch (on-contacts-event-creator (add-identity contacts-by-hash contacts))))))))

 (reg-fx
-  ::request-contacts-by-address
+  ::request-contact-by-address
   (fn [id]
     (http-post "get-contacts-by-address" {:addresses [id]}
                (fn [{:keys [contacts]}]
-                 (if (> (count contacts) 0)
-                   (let [{:keys [whisper-identity]} (first contacts)
+                 (if-let [contact (first contacts)]
+                   (let [{:keys [whisper-identity]} contact
                          contact {:name             (generate-gfy whisper-identity)
                                   :address          id
                                   :photo-path       (identicon whisper-identity)
@@ -431,7 +431,7 @@
   :add-contact-handler
   (fn [{:keys [db]} [_ id]]
     (if (spec/valid? :global/address id)
-      {::request-contacts-by-address id}
+      {::request-contact-by-address id}
       {:dispatch (if (get-in db [:contacts/contacts id])
                    [:add-pending-contact id]
                    [:add-new-contact-and-open-chat {:name             (generate-gfy id)


fix #1414 by adding necessary data to bot-db

--- src/status_im/chat/handlers/webview_bridge.cljs
+++ src/status_im/chat/handlers/webview_bridge.cljs
@@ -47,7 +47,8 @@
   (fn [db [_ bridge]]
     (assoc db :webview-bridge bridge)))

-(defn contacts-click-handler [{:keys [whisper-identity] :as contact} action params]
+(defn contacts-click-handler
+  [{:keys [whisper-identity] :as contact} action params]
   (dispatch [:navigate-back])
   (when action
     (if (= contact :qr-scan)
@@ -55,22 +56,20 @@
         (dispatch [:show-scan-qr :webview-address-from-qr])
         (dispatch [:navigate-to-modal :qr-code-view {:qr-source :whisper-identity
                                                      :amount?   true}]))
-      (dispatch [:chat-with-command whisper-identity action params]))))
+      (dispatch [:chat-with-command whisper-identity action
+                 (assoc params :contact contact)]))))

 (register-handler ::send-command
   (u/side-effect!
-    (fn [{:keys [current-chat-id] :as db} [_ command-key params]]
-      (let [command       (get-in db [:contacts current-chat-id :commands command-key])
-            command-input {:content       "0"
-                           :command       command
-                           :parameter-idx 0
-                           :params        {"amount" (:amount params)}
-                           :to-message-id nil}]
+    (fn [{:keys [current-chat-id] :as db}
+         [_ command-key {:keys [contact amount]}]]
+      (let [command (get-in db [:contacts current-chat-id :commands command-key])]
+        (dispatch [:set-in [:bot-db current-chat-id :public :recipient] contact])
         (dispatch [:proceed-command
                    {:command  command,
                     :metadata nil,
-                    :args     [(str (:amount params))]}
+                    :args     [(get contact :name) amount]}
                    current-chat-id])))))

 (defn chat-with-command


Use a *much* faster "satisfies?" alternative

--- src/cheshire/generate.clj
+++ src/cheshire/generate.clj
@@ -82,7 +82,7 @@
 (defn generate [^JsonGenerator jg obj ^String date-format ^Exception ex]
   (cond
    (nil? obj) (.writeNull ^JsonGenerator jg)
-   (:to-json (find-protocol-impl JSONable obj)) (#'to-json obj jg)
+   (get (:impls JSONable) (class obj)) (#'to-json obj jg)
    (i? IPersistentCollection obj) (condp instance? obj
                                     clojure.lang.IPersistentMap
                                     (generate-map jg obj date-format ex)


Added a status-led and safer door shutting

--- src/chicken_coop/core.clj
+++ src/chicken_coop/core.clj
@@ -41,16 +41,77 @@
        (recur))))

-(defn close-door! [hb floor-btn]
-  (log "Closing door")
-  (hb/forward! hb)
-  (wait-till (closed? floor-btn)
-    (log "Stopping door")
-    (Thread/sleep 500)
-    (hb/stop! hb)))
-
-
-(defn open-door! [hb roof-btn]
+(defn toggle!
+  [pin]
+  (if (on? pin)
+    (on! pin)
+    (off! pin)))
+
+
+(defn blink-led
+  "Given an led GPIO pin, blink for the given pattern, specified as a single ms value - or vector of such values -
+  to wait between led switching"
+  [led-pin pattern]
+  (if (number? pattern)
+    (recur led-pin [pattern])
+    (doseq [t pattern]
+      (toggle! led-pin)
+      (Thread/sleep t))))
+
+
+(def ^:dynamic status :running)
+(defn update-status!
+  [new-status]
+  (cond
+    (and (= status :warnings) (= new-status :running))
+      (log "WARNING: won't reduce status to :running from warning")
+    (= status :errors)
+      (log "WARNING: can't change status once :errors")
+    :else
+      (do
+        (log "Changing status to" new-status)
+        (def status new-status))))
+
+
+
+(defn close-door! [hb floor-btn roof-btn]
+  (log "Initiating close-door! sequence")
+  (let [door-close-wait 500 ; time to wait after door closes for latches to lock
+        n-retries       3
+        max-time-secs   120
+        lower-with-log  (fn []
+                          (log "Lowering door")
+                          (hb/forward! hb))
+        start-time      (System/currentTimeMillis)]
+    (lower-with-log)
+    (loop [tries 0]
+      (cond
+        (closed? floor-btn) (do (log "Stopping door")
+                                (Thread/sleep door-close-wait)
+                                (hb/stop! hb))
+        (and (closed? roof-btn) (tries > n-retries))
+                            (do (log "ERROR: Hit roof with max number of retries. Attempting to close without worrying about btn.")
+                                (update-status! :errors)
+                                (hb/reverse! hb)
+                                (Thread/sleep 1000)) ; exit
+        (closed? roof-btn)  (do (log "WARNING: Hit roof; reeling back in and trying again.")
+                                (update-status! :warnings)
+                                (hb/reverse! hb)
+                                (Thread/sleep 1000) ; make sure door lets go of button
+                                (wait-till (closed? roof-btn)
+                                  (log "Reeling complete; trying again.")
+                                  (lower-with-log))
+                                (recur (inc tries)))
+        (> (- (System/currentTimeMillis) start-time) max-time-secs)
+                            (do (log "ERROR: Maxed out on time; Shutting down.")
+                                (update-status! :errors)
+                                (hb/stop! hb))
+        :else               (recur tries)))))
+
+
+
+
+(defn open-door! [hb floor-btn roof-btn]
   (log "Opening door")
   (hb/reverse! hb)
   (wait-till (closed? roof-btn)
@@ -133,8 +194,18 @@
         mtr-ctrl  (hb/hbridge [16 17 18] :header :P8)
         timer     (time-sm
                     (log-tr "Initial time state:" (init-state! floor-btn roof-btn light-ain))
-                    (partial open-door! mtr-ctrl roof-btn)
-                    (partial close-door! mtr-ctrl floor-btn))]
+                    (partial open-door! mtr-ctrl floor-btn roof-btn)
+                    (partial close-door! mtr-ctrl floor-btn roof-btn))]
+
+    (future
+      (let [status-patterns {:running  [1500 3000] ; nice steady pulse
+                             :warnings [1000 1000]
+                             :errors   [200  800]}
+            status-led (gpio :P8 14 :out)]
+        (loop []
+          (blink-led status-led (status-patterns status))
+          (recur))))
+
     (loop [timer timer]
       (Thread/sleep 1000)
       (let [light-level (safe-read! light-ain)]


change `cljs.analyzer/cache-file` to return `cljs/aot/core.cljs.cache.edn` resource if available

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -1888,8 +1888,13 @@
 (defn cache-file
   ([src] (cache-file src "out"))
   ([src output-dir]
-    (let [ns-info (parse-ns src)]
-      (io/file (str (util/to-target-file output-dir ns-info "cljs") ".cache.edn")))))
+   (if-let [core-cache
+            (and (util/url? src)
+                 (.endsWith (.getPath ^URL src) (str "cljs" File/separator "core.cljs"))
+                 (io/resource "cljs/aot/core.cljs.cache.edn"))]
+     core-cache
+     (let [ns-info (parse-ns src)]
+       (io/file (str (util/to-target-file output-dir ns-info "cljs") ".cache.edn"))))))

 (defn last-modified [src]
   (cond


fixing ns declaration for compiler

fixing ns declaration for compiler

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -8,7 +8,7 @@

 (set! *warn-on-reflection* true)

-(ns cljs.compiler
+(ns clj.cljs.compiler
   (:refer-clojure :exclude [munge]))

 (def js-reserved #{"new" "debugger" "enum" "default" "private" "finally" "in" "import" "package" "with" "throw"
@@ -484,7 +484,7 @@
         :else {:op :constant :env env :form form}))))

 (comment
-(in-ns 'cljs.compiler)
+(in-ns 'clj.cljs.compiler)
 (import '[javax.script ScriptEngineManager])
 (def jse (-> (ScriptEngineManager.) (.getEngineByName "JavaScript")))
 (.eval jse bootjs)


* src/clj/cljs/compiler.clj: don't export arities to ns - just add arities as properties to multi-arity fn.

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -444,7 +444,8 @@
         (if variadic
           (emit-variadic-fn-method (assoc (first methods) :name name))
           (emit-fn-method (assoc (first methods) :name name)))
-        (let [name (or name (gensym))
+        (let [has-name? (and name true)
+              name (or name (gensym))
               maxparams (apply max-key count (map :params methods))
               mmap (into {}
                      (map (fn [method]
@@ -459,8 +460,7 @@
           (doseq [[n meth] ms]
             (println (str "var " n " = " (with-out-str (if (:variadic meth)
                                                            (emit-variadic-fn-method meth)
-                                                           (emit-fn-method meth))) ";"))
-            (println (str (munge (-> env :ns :name)) "." n) " = " n ";"))
+                                                           (emit-fn-method meth))) ";")))
           (println (str name " = function(" (comma-sep (if variadic
                                                          (concat (butlast maxparams) ['var_args])
                                                          maxparams)) "){"))
@@ -481,6 +481,10 @@
           (when variadic
             (println (str name ".cljs$lang$maxFixedArity = " max-fixed-arity ";"))
             (println (str name ".cljs$lang$applyTo = " (some #(let [[n m] %] (when (:variadic m) n)) ms) ".cljs$lang$applyTo;")))
+          (when has-name?
+            (doseq [[n meth] ms]
+              (let [c (count (:params meth))]
+               (println (str name ".__" c " = " n ";")))))
           (println (str "return " name ";"))
           (println "})()")))
       (when loop-locals
@@ -562,7 +566,7 @@
                 (let [arities (map #(-> % :params count) methods)]
                   (if (some #{arity} arities)
                     (update-in f [:info :name]
-                      (fn [name] (symbol (str name "__" arity))))
+                      (fn [name] (symbol (str name ".__" arity))))
                     f))))
             f)]
     (emit-wrap env


add column information to the source mapping structure in the compiler

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -231,7 +231,7 @@
                (name var-name)
                info)]
     (when (and (:line env) (symbol? var-name))
-      (let [{:keys [line col]} env]
+      (let [{:keys [line column]} env]
         (swap! *cljs-mappings*
           (fn [m]
             (let [minfo {:gcol  @*cljs-gen-col*
@@ -241,7 +241,7 @@
                 (fnil (fn [m]
                         (update-in m [line]
                           (fnil (fn [m]
-                                  (update-in m [(or col 0)]
+                                  (update-in m [(or column 0)]
                                     (fnil (fn [v] (conj v minfo)) [])))
                             (sorted-map))))
                   (sorted-map))))))))


Added support when prop lookup target is a invoke

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -862,6 +862,12 @@

 (defmulti build-dot-form #(map classify-sub %))

+;; (.-p (...))
+;; (. (...) -p)
+(defmethod build-dot-form [::list ::property ()]
+  [[target prop _]]
+  {:dot-action ::access :target target :field (clean-symbol prop)})
+
 ;; (.-p o)
 ;; (. o -p)
 (defmethod build-dot-form [::symbol ::property ()]


:bug: Fix unexpected exception on text drawing.

--- frontend/src/uxbox/main/data/workspace/texts.cljs
+++ frontend/src/uxbox/main/data/workspace/texts.cljs
@@ -66,6 +66,7 @@
   (cond
     (object? node) (.isText Text node)
     (map? node) (string? (:text node))
+    (nil? node) false
     :else (throw (ex-info "unexpected type" {:node node}))))

 (defn- ^boolean is-paragraph-node?
@@ -73,6 +74,7 @@
   (cond
     (object? node) (= (.-type node) "paragraph")
     (map? node) (= "paragraph" (:type node))
+    (nil? node) false
     :else (throw (ex-info "unexpected type" {:node node}))))

 (defn- ^boolean is-root-node?
@@ -80,6 +82,7 @@
   (cond
     (object? node) (= (.-type node) "root")
     (map? node) (= "root" (:type node))
+    (nil? node) false
     :else (throw (ex-info "unexpected type" {:node node}))))

 (defn- editor-current-values


Fix bug should coerce URI prefixes to strings in rdf-writer

--- src/grafter/rdf4j/io.clj
+++ src/grafter/rdf4j/io.clj
@@ -345,7 +345,7 @@

           (reduce (fn [acc [name prefix]]
                     (doto writer
-                      (.handleNamespace name prefix))) writer prefixes))))
+                      (.handleNamespace name (str prefix)))) writer prefixes))))

 (def ^:no-doc format-supports-graphs #{RDFFormat/NQUADS
                                        RDFFormat/TRIX


fix lock not removed from local storage

fix lock not removed from local storage

--- src/group_redis/core.clj
+++ src/group_redis/core.clj
@@ -94,7 +94,7 @@
       (do
         ;remove from state
         (try (dosync (alter state-ref (fn [state]
-                                   (assoc state :locks (drop-while #(= (:path %) lock-path) (:locks state))))))
+                                   (assoc state :locks (filter (complement #(= (:path %) lock-path)) (:locks state))))))
           (finally ;delete from redis
                  (car/wcar conn (car/del lock-path))))
         true)


Use Leiningen 2.0.0 for sample app project.clj

--- sample-app/project.clj
+++ sample-app/project.clj
@@ -1,16 +1,17 @@
 (defproject cljs-browser "0.0.1-SNAPSHOT"
   :description ""
-  :dependencies [[org.clojure/clojure "1.4.0-beta4"]
+  :min-lein-version "2.0.0"
+  :dependencies [[org.clojure/clojure "1.4.0"]
                  [org.clojure/clojurescript "0.0-1236"]
                  [ring "1.0.0-RC1"]
                  [compojure "0.6.4"]
                  [enlive "1.0.0"]]
-  :repl-init one.sample.repl
-  :source-path "src/app/clj"
-  :extra-classpath-dirs ["src/app/cljs"
-                         "src/app/cljs-macros"
-                         "src/lib/clj"
-                         "src/lib/cljs"
-                         "templates"
-                         "../src"
-                         "../domina/src/cljs"])
+  :repl-options {:init-ns one.sample.repl}
+  :source-paths ["src/app/clj"
+                 "src/app/cljs"
+                 "src/app/cljs-macros"
+                 "src/lib/clj"
+                 "src/lib/cljs"
+                 "templates"
+                 "../src"
+                 "../domina/src/cljs"])


fix Node file loading error reporting

fix Node file loading error reporting

--- support/src/figwheel/client/file_reloading.cljs
+++ support/src/figwheel/client/file_reloading.cljs
@@ -77,6 +77,8 @@
     (callback (try
                 (js/require path)
                 (catch js/Error e
+                  (utils/log :error (str  "Figwheel: Error loading file " path))
+                  (utils/log :error (.-stack e))
                   false)))))

 (defmethod reload-base :html [request-url callback]


Fix failing test

Fix failing test

--- src/tourbillon/event/cron.clj
+++ src/tourbillon/event/cron.clj
@@ -375,8 +375,8 @@
                                           (and (= dow 5)
                                                (or (= day (dec day-near))
                                                    (let [last-of-month (get-days-in-month month year)]
-                                                     (and (= day (- last-day-of-month 2))
-                                                          (= day-near last-day-of-month))))))))
+                                                     (and (= day (- last-of-month 2))
+                                                          (= day-near last-of-month))))))))
     ;; Should never be reached
     :else                         (constantly true)))


Add missing import on colorpicker ns.

Add missing import on colorpicker ns.

--- src/uxbox/ui/colorpicker.cljs
+++ src/uxbox/ui/colorpicker.cljs
@@ -3,6 +3,7 @@
             [rum.core :as rum]
             [cats.labs.lens :as l]
             [goog.events :as events]
+            [uxbox.util.color :refer (rgb->hex)]
             [uxbox.ui.mixins :as mx])
   (:import goog.events.EventType))

@@ -21,7 +22,7 @@
         r (aget (.-data image) 0)
         g (aget (.-data image) 1)
         b (aget (.-data image) 2)]
-    (callback {:hex (mx/rgb->hex [r g b])
+    (callback {:hex (rgb->hex [r g b])
                :rgb [r g b]})))

 (defn colorpicker-render


Fix indentation of lift-m macro.

Fix indentation of lift-m macro.

--- src/cats/core.cljc
+++ src/cats/core.cljc
@@ -324,29 +324,32 @@

 #?(:clj
    (defmacro lift-m
-    "Lifts a function with the given fixed number of arguments to a
-    monadic context.
-
-        (def monad+ (lift-m 2 +))
-
-        (monad+ (maybe/just 1) (maybe/just 2))
-        ;; => <Just [3]>
-
-        (monad+ (maybe/just 1) (maybe/nothing))
-        ;; => <Nothing>
-
-        (monad+ [0 2 4] [1 2])
-        ;; => [1 2 3 4 5 6]
-    "
-    ([f]
+     "Lifts a function with the given fixed number of arguments to a
+     monadic context.
+
+         (def monad+ (lift-m 2 +))
+
+         (monad+ (maybe/just 1) (maybe/just 2))
+         ;; => <Just [3]>
+
+         (monad+ (maybe/just 1) (maybe/nothing))
+         ;; => <Nothing>
+
+         (monad+ [0 2 4] [1 2])
+         ;; => [1 2 3 4 5 6]
+     "
+     ([f]
      (if (not (symbol? f))
-       (throw (IllegalArgumentException. "You must provide an arity for lifting anonymous functions"))
+       (throw (IllegalArgumentException.
+               "You must provide an arity for lifting anonymous functions"))
        (let [fvar (resolve f)]
          (if-let [args (arglists fvar)]
            (if (single-arity? fvar)
              `(lift-m ~(arity fvar) ~f)
-             (throw (IllegalArgumentException. "The given function is either variadic or has multiple arities, provide an arity for lifting.")))
-           (throw (IllegalArgumentException. "The given function doesn't have arity metadata, provide an arity for lifting."))))))
+             (throw (IllegalArgumentException.
+                     "The given function is either variadic or has multiple arities, provide an arity for lifting.")))
+           (throw (IllegalArgumentException.
+                   "The given function doesn't have arity metadata, provide an arity for lifting."))))))
     ([n f]
      (let [val-syms (repeatedly n gensym)
            mval-syms (repeatedly n gensym)


no need to start jetty for those tests

no need to start jetty for those tests

--- test/de/otto/tesla/stateful/app_status_test.clj
+++ test/de/otto/tesla/stateful/app_status_test.clj
@@ -13,13 +13,13 @@
             [de.otto.tesla.stateful.routes :as rts]
             [ring.mock.request :as mock]))

-(defn- test-system [runtime-config]
+(defn- serverless-system [runtime-config]
   (dissoc
     (system/empty-system runtime-config)
     :server))

 (deftest ^:unit should-have-system-status-for-runtime-config
-  (u/with-started [system (test-system {:host-name "bar" :host-port "0123"})]
+  (u/with-started [system (serverless-system {:host-name "bar" :host-port "0123"})]
                   (let [status (:app-status system)
                         system-status (:system (app-status/status-response-body status))]
                     (is (= (:hostname system-status) "bar"))
@@ -28,7 +28,7 @@

 (deftest ^:unit should-have-system-status-for-env-config
   (with-redefs-fn {#'env/env {:host-name "foo" :host-port "1234"}}
-    #(u/with-started [system (test-system {})]
+    #(u/with-started [system (serverless-system {})]
                      (let [status (:app-status system)
                            system-status (:system (app-status/status-response-body status))]
                        (is (= (:hostname system-status) "foo"))
@@ -52,15 +52,9 @@
     self))

 (defn- mock-status-system [response]
-  (c/system-map
-    :config (configuring/new-config {})
-    :metering (c/using
-                (metering/new-metering)
-                [:config])
-    :routes (routes/new-routes)
-    :app-status (c/using (app-status/new-app-status) [:config :routes])
-    :mock-status (c/using (map->MockStatusSource {:response response}) [:app-status])))
-
+  (assoc (serverless-system {})
+    :mock-status
+    (c/using (map->MockStatusSource {:response response}) [:app-status])))

 (deftest ^:unit should-show-applicationstatus
   (u/with-started [started (mock-status-system {:mock {:status  :ok
@@ -87,7 +81,7 @@

 (deftest ^:integration should-serve-health-under-configured-url
   (testing "use the default url"
-    (u/with-started [started (system/empty-system {})]
+    (u/with-started [started (serverless-system {})]
                     (let [handlers (rts/routes (:routes started))]
                       (is (= (handlers (mock/request :get "/health"))
                              {:body    "HEALTHY"
@@ -95,7 +89,7 @@
                               :status  200})))))

   (testing "use the configuration url"
-    (u/with-started [started (system/empty-system {:health-url "/my-health"})]
+    (u/with-started [started (serverless-system {:health-url "/my-health"})]
                     (let [handlers (rts/routes (:routes started))]
                       (is (= (handlers (mock/request :get "/my-health"))
                              {:body    "HEALTHY"
@@ -104,26 +98,26 @@

 (deftest ^:integration should-serve-status-under-configured-url
   (testing "use the default url"
-    (u/with-started [started (system/empty-system {})]
+    (u/with-started [started (serverless-system {})]
                     (let [handlers (rts/routes (:routes started))]
                       (is (= (:status (handlers (mock/request :get "/status")))
                              200)))))

   (testing "use the configuration url"
-    (u/with-started [started (system/empty-system {:status-url "/my-status"})]
+    (u/with-started [started (serverless-system {:status-url "/my-status"})]
                     (let [handlers (rts/routes (:routes started))]
                       (is (= (:status (handlers (mock/request :get "/my-status")))
                              200)))))

   (testing "default should be overridden"
-    (u/with-started [started (system/empty-system {:status-url "/my-status"})]
+    (u/with-started [started (serverless-system {:status-url "/my-status"})]
                     (let [handlers (rts/routes (:routes started))]
                       (is (= (handlers (mock/request :get "/status"))
                              nil))))))

 (deftest should-add-version-properties-to-status
   (testing "it should add the version properties"
-    (u/with-started [started (system/empty-system {})]
+    (u/with-started [started (serverless-system {})]
                     (let [handlers (rts/routes (:routes started))
                           response (mock/request :get "/status")
                           status-map (json/read-json (:body (handlers response)))]


CMR-1327: Addressed review comments

CMR-1327: Addressed review comments

--- umm-lib/src/cmr/umm/validation/collection.clj
+++ umm-lib/src/cmr/umm/validation/collection.clj
@@ -14,8 +14,8 @@
   (let [{:keys [granule-spatial-representation orbit-parameters]} spatial-coverage-ref]
     (if (and (= granule-spatial-representation :orbit) (nil? orbit-parameters))
       {field-path
-       [(format (str "Orbit Parameters must be defined for a collection whose "
-                     "granule spatial representation is ORBIT."))]})))
+       [(str "Orbit Parameters must be defined for a collection "
+             "whose granule spatial representation is ORBIT.")]})))

 (defn set-geometries-spatial-representation
   "Sets the spatial represention from the spatial coverage on the geometries"


CMR-2927 CMR-2928 Check for a sequence of geometries.

--- umm-lib/src/cmr/umm/validation/collection.clj
+++ umm-lib/src/cmr/umm/validation/collection.clj
@@ -30,7 +30,7 @@
    data with no reference. (ISO19115 for example)"
   [field-path spatial-coverage]
   (let [{:keys [spatial-representation granule-spatial-representation geometries]} spatial-coverage]
-    (when geometries
+    (when (seq geometries)
       (when (nil? spatial-representation)
         {field-path ["Spatial coordinate reference type must be supplied."]}))))


make sure tokens on lines are sorted

make sure tokens on lines are sorted

--- cljs/src/main/quark/cogs/editor/layouter.cljs
+++ cljs/src/main/quark/cogs/editor/layouter.cljs
@@ -67,7 +67,7 @@
         all-token-ids (map :id all-tokens)
         tokens (zipmap all-token-ids all-tokens)
         selectables (apply hash-map (concat (extract-selectables-from-code code-info) (extract-selectables-from-docs docs-info)))
-        lines-selectables (group-by :line (filter #(= (:tag %) :token) (vals selectables)))
+        lines-selectables (group-by :line (sort-by :id (filter #(= (:tag %) :token) (vals selectables))))
         selectable-parents (build-selectable-parents loc selectables)
         form-info {:id                 root-id
                    :editing            (not (empty? editing))


Auto close window after auth

Auto close window after auth

--- src/clj/five_three_one/controllers/google_auth.clj
+++ src/clj/five_three_one/controllers/google_auth.clj
@@ -7,7 +7,8 @@
             [clojure.pprint :refer [pprint]]
             ring.util.codec
             [clojure.data.json :as json]
-            [five-three-one.model.user :as model]))
+            [five-three-one.model.user :as model]
+            [hiccup.page :as page]))

 (def CLIENT_ID (:client-id env))

@@ -44,6 +45,11 @@
 (defroutes routes
   (GET "/google_login" [] (redirect red)))

+(def close-page
+  (page/html5
+   [:body
+    [:script "window.close();"]]))
+
 (defn success-handler [{{access-token :access-token} :oauth2 :as request}]
   (let [{:strs [given_name family_name email]} (get-user-data access-token)
         ;; get user from db using email,
@@ -54,7 +60,10 @@
                                     :last-name family_name
                                     :email email}))
         session (assoc-in (:session request) [:user] (:uuid user))
-        response (assoc (content-type (response "") "text/html") :session session)]
+        response (-> close-page
+                     response
+                     (content-type "text/html")
+                     (assoc :session session))]
     ;; add user data to session
     (println "from auth")
     (pprint response)


(SERVER-598) Change master routes back to regex

In PR review, it was pointed out that the changes to make
the node/catalog/report and similar routes more precise (i.e.,
by forcing a match specifically for a single node segment
in the URL as opposed to tolerating any URL structure that
followed after the `/node/`, etc., prefixes) would cause
a slight change in behavior in terms of what kind of error
the server would return on an invalid route.

This commit changes the routes back to capturing any
path following the prefixes (using a regex), and passing
matching requests down through to the Ruby layer, so that
we'll get the same error behavior we had before.

--- src/clj/puppetlabs/services/master/master_core.clj
+++ src/clj/puppetlabs/services/master/master_core.clj
@@ -23,9 +23,9 @@
    CA service."
   [request-handler]
   (comidi/routes
-    (comidi/GET ["/node/" :node] request
+    (comidi/GET ["/node/" [#".*" :rest]] request
                    (request-handler request))
-    (comidi/GET ["/facts/" :node] request
+    (comidi/GET ["/facts/" [#".*" :rest]] request
                    (request-handler request))
     (comidi/GET ["/file_content/" [#".*" :rest]] request
                    (request-handler request))
@@ -54,11 +54,11 @@
     (comidi/HEAD ["/file_bucket_file/" [#".*" :rest]] request
                    (request-handler request))

-    (comidi/GET ["/catalog/" :node] request
+    (comidi/GET ["/catalog/" [#".*" :rest]] request
                    (request-handler request))
-    (comidi/POST ["/catalog/" :node] request
+    (comidi/POST ["/catalog/" [#".*" :rest]] request
                     (request-handler request))
-    (comidi/PUT ["/report/" :node] request
+    (comidi/PUT ["/report/" [#".*" :rest]] request
                    (request-handler request))
     (comidi/GET ["/resource_type/" [#".*" :rest]] request
                    (request-handler request))


Added a genclass

Added a genclass

--- src/clojure/funcatron/tron/routers/shim_router.clj
+++ src/clojure/funcatron/tron/routers/shim_router.clj
@@ -1,4 +1,5 @@
 (ns funcatron.tron.routers.shim-router
+  (:gen-class)
   (:require [funcatron.tron.util :as fu]
             [cheshire.core :as json]
             [org.httpkit.server :as kit]


(TK-369) Use .setAliasChecks instead of .addAliasCheck for follow-links

--- src/puppetlabs/trapperkeeper/services/webserver/jetty9_core.clj
+++ src/puppetlabs/trapperkeeper/services/webserver/jetty9_core.clj
@@ -705,7 +705,7 @@
          normalize-request-uri? (:normalize-request-uri? options)]
      (.setBaseResource handler (Resource/newResource base-path))
      (if follow-links?
-       (.addAliasCheck handler (AllowSymLinkAliasChecker.))
+       (.setAliasChecks handler [(AllowSymLinkAliasChecker.)])
        (.clearAliasChecks handler))
      ;; register servlet context listeners (if any)
      (when-not (nil? context-listeners)


Switch to pub/sub model for range updates on tsplots.

--- metlog-vault/src-client/metlog_client/metlog.cljs
+++ metlog-vault/src-client/metlog_client/metlog.cljs
@@ -4,7 +4,7 @@
   (:require [reagent.core :as reagent]
             [ajax.core :as ajax]
             [cljs.reader :as reader]
-            [cljs.core.async :refer [put! close! chan <! dropping-buffer alts! pipeline]]
+            [cljs.core.async :refer [put! close! chan <! dropping-buffer alts! pipeline pub sub]]
             [cljs-time.core :as time]
             [cljs-time.coerce :as time-coerce]
             [metlog-client.tsplot :as tsplot]))
@@ -23,6 +23,34 @@
              false)))))

 (defonce query-window (reagent/atom "1d"))
+
+(defn periodic-event-channel [ interval-ms ]
+  (let [channel (chan)
+        put-now #(put! channel {:msg-type :timestamp :t (time/now)})]
+    (put-now)
+    (js/setInterval put-now interval-ms)
+    channel))
+
+(defonce time-event-channel (periodic-event-channel 15000))
+
+(defn range-ending-at [ end-t window-seconds ]
+  (let [begin-t (time/minus end-t (time/seconds window-seconds))]
+    {:msg-type :range
+     :begin-t (time-coerce/to-long begin-t)
+     :end-t (time-coerce/to-long end-t)}))
+
+(defn query-range-channel-2 [ time-event-channel ]
+  (let [ output (chan)
+        output-pub (pub output :msg-type)]
+    (go-loop [ time (time/now) qws @query-window ]
+      (>! output (range-ending-at time (parse-query-window qws)))
+      (when-let [ msg (<! time-event-channel)]
+        (case (:msg-type msg)
+          :timestamp (recur (:t msg) qws)
+          :query-window (recur time (:window-spec msg)))))
+    output-pub))
+
+(defonce update-pub (query-range-channel-2 time-event-channel))

 (defonce dashboard-state (reagent/atom {:series [] :text ""}))

@@ -48,45 +76,26 @@
 (defn fetch-series-names [ cb ]
   (ajax-get "/series-names" cb))

-(defn fetch-series-data [ series-name query-window-secs cb ]
-  (let [end-t (time/now)
-        begin-t (time/minus end-t (time/seconds query-window-secs))]
-    (ajax-get (str "/data/" series-name)
-              {:begin-t (time-coerce/to-long begin-t)
-               :end-t (time-coerce/to-long end-t)}
-              cb)))

-(defn periodic-event-channel [ interval-ms ]
-  (let [channel (chan (dropping-buffer 1))
-        put-now #(put! channel (time/now))]
-    (put-now)
-    (js/setInterval put-now interval-ms)
-    channel))
-
-(defn range-ending-at [ end-t ]
-  (let [begin-t (time/minus end-t (time/seconds (parse-query-window @query-window)))]
-    {:begin-t (time-coerce/to-long begin-t)
-     :end-t (time-coerce/to-long end-t)}))
-
-(defn query-range-channel [ periodic-event-channel ]
-  (let [ channel (chan (dropping-buffer 1)) ]
-    (pipeline 1 channel (map range-ending-at) periodic-event-channel)
-    channel))
+(defn range-ending-at-current-window [ end-t ]
+  (range-ending-at end-t (parse-query-window @query-window)))

 (defn series-data-channel [ series-name query-range-channel ]
   (let [channel (chan)]
     (go-loop []
-      (ajax-get (str "/data/" series-name) (<! query-range-channel) #(put! channel %))
-      (recur))
+      (when-let [ query-range  (<! query-range-channel)]
+        (ajax-get (str "/data/" series-name) query-range #(put! channel %))
+        (recur)))
     channel))

 (defn subscribe-plot-data [ series series-state ]
-  (let [ channel (series-data-channel series (query-range-channel (periodic-event-channel 15000))) ]
+  (let [update-out-chan (chan)
+        channel (series-data-channel series update-out-chan) ]
+    (sub update-pub :range update-out-chan)
     (go-loop []
-      (let [ data (<! channel) ]
-        (when data
-          (swap! series-state assoc :series-data data)
-          (recur))))))
+      (when-let [ data (<! channel) ]
+        (swap! series-state assoc :series-data data)
+        (recur)))))

 (defn series-tsplot [ series qws-arg ]
   (let [dom-node (reagent/atom nil)
@@ -97,7 +106,7 @@
       (fn [ this old-argv ]
         (let [canvas (.-firstChild @dom-node)
               ctx (.getContext canvas "2d")
-              range (range-ending-at (time/now))]
+              range (range-ending-at-current-window (time/now))]
           (tsplot/draw ctx (.-clientWidth canvas) (.-clientHeight canvas)
                        (:series-data @series-state)
                        (:begin-t range)
@@ -131,6 +140,7 @@

 (defn end-edit [ text state ]
   (when (parse-query-window text)
+    (put! time-event-channel {:msg-type :query-window :window-spec text})
     (reset! query-window text)))

 (defn input-field [ initial-text text-valid? on-enter ]


[dev.clj]: docs for reset and go

[dev.clj]: docs for reset and go

--- dev/dev.clj
+++ dev/dev.clj
@@ -31,13 +31,13 @@
   (tn/refresh-all))

 (defn go
-  "starts all defstate.s"
+  "starts all states defined by defstate"
   []
   (start)
   :ready)

 (defn reset
-  "stops all defstates, reloads modified source files, and restarts defstates"
+  "stops all states defined by defstate, reloads modified source files, and restarts the states"
   []
   (stop)
   (tn/refresh :after 'dev/go))


carry-debugger: bump deps

carry-debugger: bump deps

--- contrib/debugger/project.clj
+++ contrib/debugger/project.clj
@@ -1,5 +1,5 @@
 (defproject
-  carry-debugger "0.1.0"
+  carry-debugger "0.2.0"
   :description "Middleware for debugging Carry applications."
   :url "https://github.com/metametadata/carry/tree/master/contrib/debugger"
   :license {:name "MIT" :url "http://opensource.org/licenses/MIT"}
@@ -7,12 +7,12 @@
   :dependencies [[org.clojure/clojure "1.8.0" :scope "provided"]
                  [org.clojure/clojurescript "1.8.51" :scope "provided"]

-                 [carry-schema "0.2.0"]
+                 [carry-schema "0.3.0"]
                  [carry-reagent "0.2.0"]

                  [org.clojure/core.match "0.3.0-alpha4"]
                  [reagent "0.6.0-alpha2"]
-                 [prismatic/schema "1.1.0"]
+                 [prismatic/schema "1.1.1"]
                  [com.rpl/specter "0.10.0"]
                  [cljsjs/jquery-ui "1.11.4-0"]
                  [cljsjs/filesaverjs "1.1.20151003-0"]]


don't keep cluster alive after test

don't keep cluster alive after test

--- src/test/clj/com/climate/services/aws/emr_test.clj
+++ src/test/clj/com/climate/services/aws/emr_test.clj
@@ -81,23 +81,25 @@
       (s3/put-object-string bucket "data/simple.txt"
         "line1 a b
         line2 c d")
-
       (println "These tests take a long time to run, and provide no feedback while running."
                "Try 'elastic-mapreduce --list' for an idea of where it's at.")
-      (start-job-flow
-        test-flow-name
-        [(step-config
-          "stream-step"
-          false
-          "/home/hadoop/contrib/streaming/hadoop-streaming.jar"
-          nil
-          ["-input" (format "s3://%s/data/simple.txt" bucket)
-           "-output" "/out"
-           "-mapper" (format "s3://%s/scripts/wc.sh" bucket)])]
-        @*flow-args*))))
+      (let [jf (start-job-flow
+                 test-flow-name
+                 [(step-config
+                    "stream-step"
+                    false
+                    "/home/hadoop/contrib/streaming/hadoop-streaming.jar"
+                    nil
+                    ["-input" (format "s3://%s/data/simple.txt" bucket)
+                     "-output" "/out"
+                     "-mapper" (format "s3://%s/scripts/wc.sh" bucket)])]
+                 @*flow-args*)]
+        (println "Started jobflow, id =" jf)
+        jf))))

-; These tests are specified as functions rather than a test. This is a hack to force it to run before
-; test-wait-on-step.  It will fail if the cluster has already COMPLETED.
+; These tests are specified as functions rather than a test. This is a hack to
+; force it to run before test-wait-on-step.  It will fail if the cluster has
+; already COMPLETED.
 (defn test-flow-for-name-and-types
   []
   (with-emr
@@ -125,15 +127,13 @@
       (binding [;; NOTE(lbarrett): Bind flow-args to an atom because we deref
                 ;; it when it's used because it's normally a delay (so we can
                 ;; run non-integration tests).
-                *flow-args* (atom (conj @*flow-args* {:keep-alive true}))]
+                *flow-args* (atom @*flow-args*)]
         (let [jf-id (setup)
               dummy-steps (make-dummy-step)]
           (is= 1 (.size (steps-for-jobflow jf-id)))
           (add-steps jf-id [dummy-steps])
           (Thread/sleep 2000)
-          (is= 2 (.size (steps-for-jobflow jf-id)))
-          ;(terminate-flow-id jf-id)
-          )))))
+          (is= 2 (.size (steps-for-jobflow jf-id))))))))

 (defn test-step-status
   []


Changes print formatting statement, removing some characters

--- 06-code-golf/tf-06.clj
+++ 06-code-golf/tf-06.clj
@@ -6,4 +6,4 @@
                 (remove
                   #(contains? (set (.split (slurp "../stop_words.txt") ",")) %)
                   (re-seq #"[a-z]{2,}" (.toLowerCase (slurp (first *command-line-args*))))))))]
-  (printf "%s - %d\n" (first c) (nth c 1)))
+  (println (first c) "-" (nth c 1)))


:fire: Remove unused import.

:fire: Remove unused import.

--- backend/src/uxbox/services/mutations/profile.clj
+++ backend/src/uxbox/services/mutations/profile.clj
@@ -11,7 +11,6 @@
   (:require
    [clojure.spec.alpha :as s]
    [datoteka.core :as fs]
-   [datoteka.storages :as ds]
    [promesa.core :as p]
    [promesa.exec :as px]
    [sodi.prng]
@@ -25,12 +24,12 @@
    [uxbox.images :as images]
    [uxbox.media :as media]
    [uxbox.services.mutations :as sm]
+   [uxbox.services.mutations.images :as imgs]
+   [uxbox.services.queries.profile :as profile]
    [uxbox.services.util :as su]
-   [uxbox.services.queries.profile :as profile]
-   [uxbox.services.mutations.images :as imgs]
    [uxbox.util.blob :as blob]
+   [uxbox.util.storage :as ust]
    [uxbox.util.uuid :as uuid]
-   [uxbox.util.storage :as ust]
    [vertx.core :as vc]))

 ;; --- Helpers & Specs


use the output path as the asset path

use the output path as the asset path

--- src/adzerk/boot_cljs/middleware.clj
+++ src/adzerk/boot_cljs/middleware.clj
@@ -56,7 +56,7 @@
   foo.bar CLJS namespace with output to foo/bar.js)."
   [{:keys [tmp-src tmp-out main] :as ctx} write-main?]
   (let [out-rel-path (cljs-edn-path->output-dir-path (:rel-path main))
-        asset-path   (util/get-name out-rel-path)
+        asset-path   out-rel-path
         out-file     (io/file tmp-out out-rel-path)
         out-path     (.getPath out-file)
         js-path      (util/path tmp-out (cljs-edn-path->js-path (:rel-path main)))


Set print-length to 10 for every repl by default.

--- lein/.lein/profiles.clj
+++ lein/.lein/profiles.clj
@@ -15,6 +15,7 @@
  :repl {:dependencies [[acyclic/squiggly-clojure "0.1.6"]
                        [datomic-schema-grapher "0.0.1"]
                        [org.clojure/tools.nrepl "0.2.12"]]}
+ :repl-options {:init (set! *print-length* 10)}
  ;; VisualVM profiling opts
  :jvm-opts ["-Dcom.sun.management.jmxremote"
             "-Dcom.sun.management.jmxremote.ssl=false"


Test case: catch Throwable, not only Exception.

Test case is following:
1. bind r.s/*exception-steam* to fn collecting exception
2. run stream where user code throws j.l.Throwable
3. check if exception was collected by *exception-stream*

--- test/riemann/test/streams.clj
+++ test/riemann/test/streams.clj
@@ -145,7 +145,16 @@
                       (s {:metric 2})
                       (is (nil? @e))
                       (advance! 1)
-                      (is (= "error" (:state @e)))))))
+                      (is (= "error" (:state @e))))))
+
+         (testing "exception handling takes care of Throwables"
+                  (logging/suppress
+                   "riemann.streams"
+                   (let [exceptions (atom [])]
+                     (binding [riemann.streams/*exception-stream* #(swap! exceptions conj %)]
+                       (run-stream (sdo #(throw (Throwable. %)))
+                                   ["boo!"]))
+                     (is (= 1 (count @exceptions)))))))

 (deftest execute-on-test
          (let [output (atom [])


Removed count-ts function

Removed count-ts function

--- src/clj/forma/hadoop/jobs/forma.clj
+++ src/clj/forma/hadoop/jobs/forma.clj
@@ -147,10 +147,6 @@
         (series-end ?ndvi ?start :> ?end)
         (:distinct false))))

-(defn count-series
-  [series]
-  (count (first series)))
-
 (defbufferop consolidator
   [tuples]
   [[[(vec (map first tuples))]


Extra/stats, cron fixes

Extra/stats, cron fixes

--- src/clj/salava/extra/stats/cron.clj
+++ src/clj/salava/extra/stats/cron.clj
@@ -8,12 +8,13 @@
             [clojure.data.json :as json]))

 (defn- push-stats [ctx badge-hits]
-  (let [payload (json/write-str {:social_hits badge-hits
-                                 :source (get-in ctx [:config :core :site-url])
-                                 :ts (System/currentTimeMillis)})
-        checksum (u/hmac-sha256-hex payload (get-in ctx [:config :factory :secret]))
-        url (str (get-in ctx [:config :factory :url]) "/c/badge/passport_stats?&c=" checksum)]
-    (http/http-post url {:body payload})))
+  (when (get-in ctx [:config :factory])
+    (let [payload (json/write-str {:social_hits badge-hits
+                                   :source (get-in ctx [:config :core :site-url])
+                                   :ts (System/currentTimeMillis)})
+          checksum (u/hmac-sha256-hex payload (get-in ctx [:config :factory :secret]))
+          url (str (get-in ctx [:config :factory :url]) "/c/badge/passport_stats?&c=" checksum)]
+      (http/http-post url {:body payload}))))

 (defn- id->assertion-url [ctx badge-hits]
   (let [db-conn (:connection (u/get-db ctx))
@@ -35,7 +36,7 @@
             {} (line-seq rdr))))

 (defn every-hour [ctx]
-  (let [conf (get-in ctx [:config :extra :stats])]
+  (let [conf (get-in ctx [:config :extra/stats])]
     (when (= (get-in ctx [:-cron :hour]) (get conf :run-at 1))
       (log/info "stats/hit-count: started working")
       (->> (hit-count (:source-file conf) (:services conf))


exclude alias in docker utils to remove warnings

--- src/cljc/swarmpit/docker/utils.cljc
+++ src/cljc/swarmpit/docker/utils.cljc
@@ -1,5 +1,6 @@
 (ns swarmpit.docker.utils
   "Utility ns for docker domain"
+  (:refer-clojure :exclude [alias])
   (:require [clojure.string :as str]))

 (defn trim-stack


WIP theme builder

WIP theme builder

--- src/cljs/koeeoadi/themebuilder.cljs
+++ src/cljs/koeeoadi/themebuilder.cljs
@@ -1,6 +1,7 @@
 (ns koeeoadi.themebuilder
-  (:require [koeeoadi.config :refer [app-state]]
-            [cljs.pprint :as pprint]))
+  (:require [koeeoadi.reconciler :refer [reconciler]]
+            [cljs.pprint :as pprint]
+            [cljs.reader :as reader]))

 (defn face-to-emacs [face-name]
   (cond (= face-name "default")
@@ -9,7 +10,6 @@
         (str "font-lock-" face-name "-face")))

 (defn emacs-theme [name faces-by-name colors-by-id]
-  ;;'(font-lock-warning-face ((t (:foreground "yellow"))))
   (let [doc    (pr-str "A theme created with Koeeoadi")
         bg-rgb (pr-str (let [[_ color-id] (get-in faces-by-name ["background" :face/color])]
                          (get-in colors-by-id [color-id :color/rgb])))]
@@ -20,8 +20,10 @@
               ([face-name property]
                (let [face-name-emacs (face-to-emacs face-name)
                      face            (get faces-by-name face-name)
-                     face-color-id   (last (:face/color face))
-                     fg-rgb          (pr-str (get-in colors-by-id [face-color-id :color/rgb]))]
+                     fg-color-id     (last (:face/color-fg face))
+                     bg-color-id     (last (:face/color-bg face))
+                     fg-rgb          (pr-str (get-in colors-by-id [fg-color-id :color/rgb]))
+                     bg-rgb          (pr-str (get-in colors-by-id [bg-color-id :color/rgb]))]
                  ;; TODO This is gross because cljs doesn't support interning
                  ;; Need to cleanup
                  (if (= face-name "default")
@@ -32,6 +34,7 @@

       `(~'progn
         (~'eval (~'read ~(str "(deftheme " name " " doc ")")))
+        ;;(~'eval (~'deftheme ~name ~doc))
         ;; adds someproperties to that theme
         (~'put (~'read ~(str name)) (quote ~'theme-immediate) ~'t)
         ;; executes in color scope
@@ -47,20 +50,60 @@
          ~(spec "keyword")
          ~(spec "negation-char")
          ~(spec "preprocessor")
-         ~(spec "regexp-grouping-backslash")
-         ~(spec "regexp-grouping-construct")
          ~(spec "string")
          ~(spec "type")
          ~(spec "variable-name")
-         ~(spec "warning"))
-        (~'provide-theme (~'read ~(str name)))))))
+         (~'provide-theme (~'read ~(str name))))))))
+
+
+;;'(font-lock-warning-face ((t (:foreground "yellow" :background ... :italic ... :weight ... ))))
+(defn font-lock-faceify [[face-name props :as pair]]
+  (let [face-name' (str "font-lock-" face-name "-face")]
+    (if (= face-name "default")
+      pair
+      (vector face-name' (assoc props :face/name face-name')))))
+
+(defn xform-prop-emacs [[k v]]
+  (when v
+    (let [rec @reconciler]
+      (case (name k)
+        "color-fg"  `(:foreground ~(:color/rgb (get-in rec v)))
+        "color-bg"  `(:background ~(:color/rgb (get-in rec v)))
+        "bold"      `(:weight     ~'bold)
+        "italic"    `(:italic     ~'t)
+        "underline" `(:underline  ~'t)
+        nil))))
+
+(defn xform-face-emacs [{:keys [face/name] :as face}]
+  ;; TODO could use transducers here to optimize
+  (let [plist (filter identity (map xform-prop-emacs face))]
+    `(~(reader/read-string name) ((~'t ~(flatten plist))))))
+
+(defn xform-faces-emacs [default-faces-map user-faces-map]
+  (let [default-faces-map' (into {} (map font-lock-faceify default-faces-map))
+        bg-color           (get-in default-faces-map ["background" :face/color-fg])]
+    (map xform-face-emacs (-> default-faces-map'
+                            ;; remove background face
+                            (dissoc "background")
+                            ;; inject original bg color into default face (emacs sets its background through the default face)
+                            (assoc-in ["default" :face/color-bg] bg-color)
+                            ;; to list
+                            vals
+                            ;; combine with the user defined emacs faces
+                            (concat (filter #(= :emacs (:face/editor %)) (vals user-faces-map)))))))
+
+;; (pprint/pprint (xform-default-faces-emacs (:faces/by-name @reconciler) (:user-faces/by-name @reconciler)))

 ;; TODO use a multimethod here
 (defn build-emacs []
-  (let [{current-theme :theme/name
-         faces-by-name :faces/by-name
-         colors-by-id  :colors/by-id} @app-state]
-    (pr-str (emacs-theme current-theme faces-by-name colors-by-id))))
+  (let [{current-theme      :theme/name
+         faces-by-name      :faces/by-name
+         user-faces-by-name :user-faces/by-name} @reconciler
+
+        user-faces-by-name'  (collect-user-faces-emacs user-faces-by-name)
+        xformed-faces-list   (xform-faces-emacs (merge user-faces-by-name faces-by-name))]
+    (pr-str (emacs-theme current-theme faces-by-name' colors-by-id))))
+

 (defn build-vim []
   "stub")


Card search

Card search

--- src/cljs/netrunner/cardbrowser.cljs
+++ src/cljs/netrunner/cardbrowser.cljs
@@ -52,16 +52,22 @@
     (for [option options]
       [:option {:value option} option])))

-(defn filter-cards [cards filter-value field]
+(defn filter-cards [filter-value field cards]
   (if (= filter-value "All")
     cards
     (filter #(= (field %) filter-value) cards)))
+
+(defn match [query cards]
+  (if (empty? query)
+    cards
+    (filter #(if (= (.indexOf (.toLowerCase (:title %)) query) -1) false true) cards)))

 (defn card-browser [cursor owner]
   (reify
     om/IInitState
     (init-state [this]
-      {:set-filter "All"
+      {:search-query ""
+       :set-filter "All"
        :type-filter "All"
        :side-filter "All"
        :faction-filter "All"
@@ -79,7 +85,7 @@
        [:div.cardbrowser
         [:div.blue-shade.panel.filters
          [:input {:type "text" :placeholder "Search cards"
-                  :on-change #()}]
+                  :on-change #(om/set-state! owner :search-query (.. % -target -value))}]

          (for [filter [["Set" :set-filter (map :name (:sets cursor))]
                        ["Side" :side-filter ["Corp" "Runner"]]
@@ -93,11 +99,12 @@

         [:div.card-list
          (om/build-all card-view
-                       (-> (:cards cursor)
-                           (filter-cards (:set-filter state) :setname)
-                           (filter-cards (:side-filter state) :side)
-                           (filter-cards (:faction-filter state) :faction)
-                           (filter-cards (:type-filter state) :type)))]]))))
+                       (->> (:cards cursor)
+                            (filter-cards (:set-filter state) :setname)
+                            (filter-cards (:side-filter state) :side)
+                            (filter-cards (:faction-filter state) :faction)
+                            (filter-cards (:type-filter state) :type)
+                            (match (.toLowerCase (:search-query state)))))]]))))

 (om/root card-browser app-state {:target (. js/document (getElementById "cardbrowser"))})


Fix id of executor issue

Fix id of executor issue

--- src/cider_ci/dispatcher/sync/update_executor.clj
+++ src/cider_ci/dispatcher/sync/update_executor.clj
@@ -60,9 +60,7 @@

 (defn update-version [executor data]
   (let [executor-version (-> data :status :version)
-        ; TODO this is broken must be mix out of :version_mismatch and executor id
-        ; see also place where it is deleted!
-        issue-id (clj-uuid/v5 clj-uuid/+null+ :version_mismatch)
+        issue-id (clj-uuid/v5 clj-uuid/+null+ (str :version_mismatch (:id executor)))
         where-clause ["executor_id = ? AND id = ?" (:id executor) issue-id]]
     (if (= executor-version cider-ci.self/VERSION)
       (jdbc/delete! (get-ds) :executor_issues where-clause)


Add randomly macro example

Add randomly macro example

Please enter the commit message for your changes. Lines starting
with '#' will be ignored, and an empty message aborts the commit.
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
        modified:   src/clojure/clojure_walkthrough/cjia/ch07_xx.clj
m

--- src/clojure/clojure_walkthrough/cjia/ch07_xx.clj
+++ src/clojure/clojure_walkthrough/cjia/ch07_xx.clj
@@ -135,3 +135,27 @@

 ;; time:

+(time (* 1331 13531)) ; 18009761
+
+;; Let's implement our own
+(defmacro time [expr]
+  `(let [start# (. System (nanoTime))
+         ret# ~expr]
+     (prn
+      (str "Elapsed time:"
+           (/ (double (- (. System (nanoTime)) start#)) 10000000.0)
+           " msecs"))
+     ret#)) ; #'clojure-walkthrough.cjia.ch07-xx/time
+
+(time (* 1345 5979)) ; 8041755
+
+;; 7.3: writing our own macro
+
+(defmacro randomly [& exprs]
+  (let [len (count exprs)
+        index (rand-int len)
+        conditions (map #(list '= index %) (range len))]
+    `(cond ~@(interleave conditions exprs))))
+
+(randomly (println "Amit") (println "Deepthi" (println "Adi")))
+(macroexpand-1 '(randomly (println "Amit") (println "Deepthi" (println "Adi")))) ; (clojure.core/cond (= 0 0) (println "Amit") (= 0 1) (println "Deepthi" (println "Adi")))


:circle-tangent instruction (already had the function)

--- src/demo/examples/plane_geometry/definitions.clj
+++ src/demo/examples/plane_geometry/definitions.clj
@@ -405,6 +405,17 @@
     (d/push-onto :boolean :result)))

+(def circle-tangent?
+  (i/build-instruction
+    circle-tangent?
+    "`:circle-tangent?` pops the top two `:circle` items, and pushes `true` if they are tangent (either one external to the other, or one inside the other) but not coincident"
+    :tags #{:plane-geometry :construction}
+    (d/consume-top-of :circle :as :arg2)
+    (d/consume-top-of :circle :as :arg1)
+    (d/calculate [:arg1 :arg2] #(circles-tangent? %1 %2) :as :result)
+    (d/push-onto :boolean :result)))
+
+
 (def line-coincide?
   (i/build-instruction
     line-coincide?
@@ -475,7 +486,7 @@
 ; [X] `:circle-nested?`
 ; [X] `:circle-inside?`
 ; [X] `:circle-surrounds?`
-; [ ] `:circle-tangent?` (to another circle)
+; [X] `:circle-tangent?` (to another circle)
 ; [ ] `:circle-intersections` (with another circle)
 ; [ ] `:LC-intersect?` (line-circle)
 ; [ ] `:LC-tangent?` (line-circle)
@@ -533,4 +544,5 @@
       (t/attach-instruction circle-nested?)
       (t/attach-instruction circle-separate?)
       (t/attach-instruction circle-surrounds?)
+      (t/attach-instruction circle-tangent?)
       ))


Fixed issue #27

Fixed issue #27

--- src/alfresco_technical_validation/validation.clj
+++ src/alfresco_technical_validation/validation.clj
@@ -48,11 +48,14 @@

 (defn- build-loc-bookmarks
   [locs type]
-  (let [[f l] (get locs type)
-        files (if (or (nil? f) (s/blank? f)) "0" f)
-        loc   (if (or (nil? l) (s/blank? l)) "0" l)]
-    { (str type "Files") files
-      (str type "LOC")   loc }))
+  (let [[f l] (get locs type)]
+    (if (and (or (nil? f) (s/blank? f))
+             (or (nil? l) (s/blank? l)))
+      nil
+      (let [files (if (or (nil? f) (s/blank? f)) "0" f)
+            loc   (if (or (nil? l) (s/blank? l)) "0" l)]
+        { (str type "Files") files
+          (str type "LOC")   loc }))))

 (defn- count-file-type-from-source
   [bookmark-name file-type source-index]
@@ -113,7 +116,7 @@
   [files-by-type]
   (let [build-tools (s/join ","
                             (filter #(not (nil? %))
-                                    (vector (if (not-empty (:ant       files-by-type)) (if (empty? (mg/grep-files #"antlib:org\.apache\.ivy\.ant" (:ant files-by-type)))
+                                    (vector (if (not-empty (:ant       files-by-type)) (if (empty? (mg/grep #"antlib:org\.apache\.ivy\.ant" (:ant files-by-type)))
                                                                                "Ant"
                                                                                "Ivy"))
                                             (if (not-empty (:maven     files-by-type)) "Maven")


implement basic add entity modal

implement basic add entity modal

--- src/cljs/flow_editor/views/modals/add_entity.cljs
+++ src/cljs/flow_editor/views/modals/add_entity.cljs
@@ -1,5 +1,30 @@
-(ns flow-editor.views.modals.add-entity)
+(ns flow-editor.views.modals.add-entity
+  (:require [reagent.core :as r]
+            [re-frame.core :refer [dispatch]]
+            [re-com.core :refer [title button v-box h-box modal-panel input-text line]]))

 (defn add-entity-modal []
-  [:div {:class-name "add-entity-modal"} "add-entity-modal"])
+  (let [entity-id (r/atom "")]
+    (fn []
+      [modal-panel
+       :child [v-box
+               :children [[title
+                           :label "Enter entity id"
+                           :level :level2
+                           :margin-bottom "20px"]
+                          [input-text
+                           :model @entity-id
+                           :on-change #(reset! entity-id %)
+                           :placeholder "Entity id"]
+                          [line
+                           :color "#ddd" :style {:margin "20px"}]
+                          [h-box
+                           :gap "12px"
+                           :children [[button
+                                       :label "Create"
+                                       :class "btn-primary"
+                                       :on-click #(dispatch [:runtime-update/add-entity @entity-id])]
+                                      [button
+                                       :label "Cancel"
+                                       :on-click #(dispatch [:modals/close])]]]]]])))


fix mongo nested fields

fix mongo nested fields

--- src/metabase/driver/query_processor/annotate.clj
+++ src/metabase/driver/query_processor/annotate.clj
@@ -25,7 +25,16 @@
   (let [fields (transient [])]
     (clojure.walk/prewalk (fn [f]
                             (if-not (= (type f) metabase.driver.query_processor.expand.Field) f
-                                    (conj! fields f)))
+                                    (let [[_ first-name] (expand/qualified-name-components f)]
+                                      (conj! fields f)
+                                      ;; HACK !!!
+                                      ;; Nested Mongo fields come back inside of their parent when you specify them in the fields clause
+                                      ;; e.g. (Q fields venue...name) will return rows like {:venue {:name "Kyle's Low-Carb Grill"}}
+                                      ;; Until we fix this the right way we'll just include the parent Field in the :query-fields list so the pattern
+                                      ;; matching works correctly.
+                                      ;; (This hack was part of the old annotation code too, it just sticks out better because it's no longer hidden amongst the others)
+                                      (when (:parent f)
+                                        (conj! fields (:parent f))))))
                           query)
     (assoc query
            :result-keys  (vec (sort (keys (first results))))
@@ -61,8 +70,8 @@

 (defn- fieldo [{:keys [query-fields], :as query} field]
   (all (conde
-        ((aggregate-fieldo query field))
-        ((membero field query-fields)))
+        ((membero field query-fields))
+        ((aggregate-fieldo query field)))
        (valid-nameo query field)))

@@ -153,13 +162,13 @@
           (every? map? %)]}
   (let [num-cols (count (:result-keys query))
         cols     (vec (lvars num-cols))]
-    (first (run 1 [q]
-             (== q cols)
-             (distincto q)
-             (everyg (partial fieldo query) q)
-             (everyg (fn [i]
-                       (fields< query (cols i) (cols (inc i))))
-                     (range 0 (dec num-cols)))))))
+    (time (first (run 1 [q]
+                   (== q cols)
+                   (distincto q)
+                   (everyg (partial fieldo query) q)
+                   (everyg (fn [i]
+                             (fields< query (cols i) (cols (inc i))))
+                           (range 0 (dec num-cols))))))))

 ;;; # ---------------------------------------- COLUMN DETAILS  ----------------------------------------
@@ -210,10 +219,10 @@
 (defn post-annotate [qp]
   (fn [query]
     (let [results (qp query)
-          cols    (time (->> (query-add-info (:query query) results)
-                             resolve+order-cols
-                             (map format-col)
-                             add-fields-extra-info))
+          cols    (->> (query-add-info (:query query) results)
+                       resolve+order-cols
+                       (map format-col)
+                       add-fields-extra-info)
           columns (map :name cols)]
       {:cols    (vec (for [col cols]
                        (update col :name name)))


test/internal/idserver/client.clj: fix ns syntax

--- src/org/altlaw/test/internal/idserver/client.clj
+++ src/org/altlaw/test/internal/idserver/client.clj
@@ -1,7 +1,7 @@
 (ns org.altlaw.test.internal.idserver.client
-  (use org.altlaw.internal.idserver.client
-       clojure.contrib.test-is)
-  (require org.altlaw.test.internal))
+  (:use org.altlaw.internal.idserver.client
+        clojure.contrib.test-is)
+  (:require org.altlaw.test.internal))

 (use-fixtures :once
               org.altlaw.test.internal/internal-server-fixture


Added bullets, which never expire or collide with anything.

--- Clojure/clojuroids.clj
+++ Clojure/clojuroids.clj
@@ -13,6 +13,8 @@
 (def angular-acceleration 10.0)
 (def width 640)
 (def height 480)
+(def fire-delay 0.3)
+(def bullet-velocity 100)

 (defn do-mod [coll func v]
     (dosync (alter coll (fn [x] (apply func [x v])))))
@@ -23,6 +25,13 @@
         (.addPoint 10 0)
         (.addPoint -3 5)
         (.addPoint -3 -5)))
+
+(defn bullet-shape []
+    (doto
+        (new Polygon)
+        (.addPoint 2 0)
+        (.addPoint -2 1)
+        (.addPoint -2 -1)))

 (defn draw-player [player g]
     (do
@@ -59,6 +68,15 @@
             (.fill g (asteroid-shape (:radii asteroid)))
             (.setTransform g old-transform))))

+(defn draw-bullet [bullet g]
+    (do
+        (.setColor g (Color/YELLOW))
+        (let [old-transform (.getTransform g)]
+            (.translate g (:x bullet) (:y bullet))
+            (.rotate g (:a bullet))
+            (.fill g (bullet-shape))
+            (.setTransform g old-transform))))
+
 (defn game-render [state g]
     (do
         (.setRenderingHint g
@@ -71,7 +89,8 @@
         (let [rect (.getClipBounds g)]
             (.fillRect g (.x rect) (.y rect) (.width rect) (.height rect)))
         (draw-player (:player state) g))
-        (doseq [a (:asteroids state)] (draw-asteroid a g)))
+        (doseq [a (:asteroids state)] (draw-asteroid a g))
+        (doseq [b (:bullets state)] (draw-bullet b g)))

 (defn create-component [game-state]
     (doto
@@ -110,6 +129,7 @@
 (defn default-state [] {
     :time (now)
     :player { :x 100.0 :y 100.0 :xv 0.0 :yv 0.0 :a 0.0 :av 0.0 }
+    :next-fire-time (now)
     :asteroids (take 10 (repeatedly generate-asteroid))
 } )

@@ -136,18 +156,45 @@
                 player)
         eff
             (Math/pow efficiency time-step)
+
+        player
+            (step-thing player time-step eff)
         ]
-    (step-thing player time-step eff)))
+    player))

 (defn asteroid-step [asteroid time-step]
     (step-thing asteroid time-step 1.0))

+(defn new-bullet [player]
+    (assoc player
+        :xv (+ (:xv player) (* (Math/cos (:a player)) bullet-velocity))
+        :yv (+ (:yv player) (* (Math/sin (:a player)) bullet-velocity))
+))
+
+(defn bullet-step [bullet time-step]
+    (step-thing bullet time-step 1.0))
+
 (defn game-step [state keys-pressed]
-    (let [new-time (now) time-step (- new-time (:time state))]
+    (let [
+        new-time (now)
+        time-step (- new-time (:time state))
+        spawn-new-bullet (and (contains? keys-pressed KeyEvent/VK_SPACE) (>= new-time (:next-fire-time state)))
+        ]
         (assoc state
             :time new-time
             :player (player-step (:player state) time-step keys-pressed)
             :asteroids (map (fn [a] (asteroid-step a time-step)) (:asteroids state))
+            :bullets
+                (map (fn [b] (bullet-step b time-step))
+                    (concat
+                        (if spawn-new-bullet
+                            [(new-bullet (:player state))]
+                            [])
+                    (:bullets state)))
+            :next-fire-time
+                (if spawn-new-bullet
+                    (+ new-time fire-delay)
+                    (:next-fire-time state))
 )))

 (defn create-game []


More idiomatic usage of macros

More idiomatic usage of macros

--- src/jobless_clj/core.clj
+++ src/jobless_clj/core.clj
@@ -11,30 +11,30 @@
 (defmacro cv-item [item]
   `(defn ~(symbol item) [arg#] {~(keyword item) arg#}))

+(defmacro cv-items [& items]
+  `(do ~@(for [n items] `(cv-item ~n))))
+
+
+
 (defmacro cv-group [group-type group-name]
   `(defn ~(symbol group-type) [& args#]
      (let [items# (map :entry (filter #(some? (:entry %1)) args#))]
        {:group {:items items# :type ~group-type :name ~group-name}})))

+(defmacro cv-groups [& groups]
+  `(do ~@(for [n groups] `(cv-group ~(first n) ~(second n)))))

-(cv-group "employment" "Employment")
-(cv-group "education" "Education")
-(cv-group "open-source" "Open Source")
-(cv-group "other-exp" "Other Experience")
+(cv-items "address" "bulletin" "company" "cv-name" "description" "email" "email"
+          "end-date" "homepage" "location" "start-date" "technologies" "title")
+(cv-groups ["employment" "Employment"]
+           ["education" "Education"]
+           ["open-source" "Open Source Projects"]
+           ["other-exp" "Other Experience"])
+;(cv-group "employment" "Employment")
+;(cv-group "education" "Education")
+;(cv-group "open-source" "Open Source")
+;(cv-group "other-exp" "Other Experience")

-(cv-item "cv-name")
-(cv-item "technologies")
-(cv-item "homepage")
-(cv-item "email")
-(cv-item "title")
-(cv-item "bulletin")
-(cv-item "email")
-(cv-item "location")
-(cv-item "address")
-(cv-item "start-date")
-(cv-item "end-date")
-(cv-item "company")
-(cv-item "description")

 (defn entry [& args]
   (let [bulletins (map :bulletin (filter #(some? (:bulletin %1)) args))


jar build with exit on close

jar build with exit on close

--- src/temperaments/core.clj
+++ src/temperaments/core.clj
@@ -1061,7 +1061,7 @@
                                      :listen [:action melody-chooser])
                            ])))

-;(config! control-frame :on-close :exit)
+(config! control-frame :on-close :exit)

 (defn -main [& args]
   (-> control-frame pack! show!)


escaping text

escaping text

--- src/text_stream/edits.clj
+++ src/text_stream/edits.clj
@@ -1,5 +1,5 @@
 (ns text-stream.edits
-  (:gen-class))
+  (:require [hiccup.utils :refer escape-html]))

 (defn consolidate
   "Takes a seq of edits and composes them into a single function. Applies from
@@ -119,5 +119,5 @@
     (let [func (get commands cmd)
           text-input (subs text (inc cmd-len))]
       (if-let [valid-input ((get cmd-validators func)
-                            (clojure.string/escape text-input) source-map)]
+                            (escape-html text-input) source-map)]
         ((func valid-input) source-map)))))


Make many simplifications to the wip collimp code.

--- src/uxbox/cli/collimp.clj
+++ src/uxbox/cli/collimp.clj
@@ -6,8 +6,8 @@

 (ns uxbox.cli.collimp
   "Collection importer command line helper."
-  (:require [clojure.pprint :refer (pprint)]
-            [clojure.edn :as edn]
+  (:require [clojure.spec :as s]
+            [clojure.pprint :refer [pprint]]
             [clojure.java.io :as io]
             [mount.core :as mount]
             [cuerdas.core :as str]
@@ -16,24 +16,30 @@
             [storages.util :as fs]
             [uxbox.config]
             [uxbox.db :as db]
-            [uxbox.cli.sql :as sql]
             [uxbox.migrations]
             [uxbox.media :as media]
+            [uxbox.cli.sql :as sql]
+            [uxbox.util.spec :as us]
+            [uxbox.util.cli :as cli]
             [uxbox.util.uuid :as uuid]
             [uxbox.util.data :as data])
   (:import [java.io Reader PushbackReader]
            [javax.imageio ImageIO]))

-;; --- Constants
+;; --- Constants & Specs

 (def ^:const +imates-uuid-ns+ #uuid "3642a582-565f-4070-beba-af797ab27a6e")

+(s/def ::name string?)
+(s/def ::type keyword?)
+(s/def ::path string?)
+(s/def ::regex us/regex?)
+
+(s/def ::import-entry
+  (s/keys :req-un [::name ::type ::path ::regex]))
+
 ;; --- CLI Helpers

-(defn exit
-  ([] (exit 0))
-  ([code]
-   (System/exit code)))

 (defn printerr
   [& args]
@@ -100,10 +106,9 @@
         sqlv (sql/create-image params)]
     (sc/execute conn sqlv)))

-(defn- import-image-from-path
+(defn- import-image
   [conn id fpath]
-  {:pre [(uuid? id)
-         (fs/path? fpath)]}
+  {:pre [(uuid? id) (fs/path? fpath)]}
   (let [imageid (uuid/namespaced +imates-uuid-ns+ (str id fpath))]
     (if-let [image (retrieve-image conn imageid)]
       (do
@@ -111,51 +116,35 @@
         (create-image conn id imageid fpath))
       (create-image conn id imageid fpath))))

-(defn- process-images-entry-by-dir
-  [conn {:keys [path id regex] :as entry}]
-  {:pre [(fs/path? path)
-         (uuid? id)
-         (instance? java.util.regex.Pattern regex)]}
-  (doseq [fpath (fs/list-files path)]
-    (when (re-matches regex (str fpath))
-      (import-image-from-path conn id fpath))))
-
-(defn- process-images-entry-by-list
-  [conn {:keys [data id] :as entry}]
-  {:pre [(uuid? id)
-         (set? data)]}
-  (doseq [item data]
-    (import-image-from-path conn id name (fs/path item))))
-
 (defn- process-images-entry
-  [conn {:keys [type] :as entry}]
-  {:pre [(keyword? type)]}
-  (let [id (create-image-collection conn entry)
-        entry (assoc entry :id id)]
-    (case type
-      :dir (process-images-entry-by-dir conn entry)
-      :list (process-images-entry-by-list conn entry))))
+  [conn {:keys [path regex] :as entry}]
+  {:pre [(s/valid? ::import-entry entry)]}
+  (let [id (create-image-collection conn entry)]
+    (doseq [fpath (fs/list-files path)]
+      (when (re-matches regex (str fpath))
+        (import-image conn id fpath)))))

 ;; --- Entry Point

-(defn- check-path
+(defn- check-path!
   [path]
   (when-not path
-    (printerr "No path is provided.")
-    (exit -1))
+    (cli/print-err! "No path is provided.")
+    (cli/exit! -1))
   (when-not (fs/exists? path)
-    (printerr "Path does not exists.")
-    (exit -1))
+    (cli/print-err! "Path does not exists.")
+    (cli/exit! -1))
   (when (fs/directory? path)
-    (printerr "The provided path is a directory.")
-    (exit -1))
+    (cli/print-err! "The provided path is a directory.")
+    (cli/exit! -1))
   (fs/path path))

 (defn- read-import-file
   [path]
-  (let [path (check-path path)
+  (let [path (check-path! path)
+        parent (fs/parent path)
         reader (pushback-reader (io/reader path))]
-    (read reader)))
+    [parent (read reader)]))

 (defn- start-system
   []
@@ -169,15 +158,15 @@
   (mount/stop))

 (defn- run-importer
-  [data]
+  [directory data]
   (println "Running importer on:")
   (pprint data))

 (defn main
   [& [path]]
-  (let [data (read-import-file path)]
+  (let [[directory data] (read-import-file path)]
     (start-system)
     (try
-      (run-importer data)
+      (run-importer directory data)
       (finally
         (stop-system)))))