cleanup; remove recursion; use mapcat instead

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -16,65 +16,28 @@

 ;; use map or pmap.
 (def ^:const mapfn pmap)
-
 (def ^:dynamic *extra-diagnostics* false)

 (defn overh
   "add given head as the head child of the phrase: parent."
   [parent head]
-  (when (and (map? parent)
-             (map? head))
-    (do
-      (log/trace (str "overh: parent: " (get-in parent [:rule])))
-      (log/trace (str "overh: head: " (get-in head [:rule] (str "head is a lexeme with pred: " (strip-refs (get-in head [:synsem :sem :pred]))))))
-      (log/trace (str "overh: parent: " parent))
-      (log/trace (str "overh: head: " head))))
   ;; TODO: get rid of all this type-checking and use
   ;; whatever people use for Clojure argument type-checking.
   (cond
-
-   (nil? head)
-   nil
-
-   (or
-    (seq? parent)
-    (set? parent)
-    (vector? parent))
-   (let [parents (lazy-seq parent)]
-     (filter (fn [result]
-               (not (fail? result)))
-             (mapcat (fn [each-parent]
-                       (overh each-parent head))
-                     parents)))
-
-   (or (set? head)
-       (vector? head))
-   (do (log/trace "head is a set: converting to a seq.")
-       (overh parent (lazy-seq head)))
-
-   (seq? head)
-   (let [head-children head]
-     (log/trace (str "head is a seq - actual type is " (type head)))
-     (filter (fn [result]
-               (not (fail? result)))
-             (mapcat (fn [child]
-                       (overh parent child))
-                     head-children)))
-   true
-   ;; TODO: 'true' here assumes that both parent and head are maps: make this assumption explicit,
-   ;; and save 'true' for errors.
-   (let [result (unify (copy parent)
-                       {:head (copy head)})
-
-         is-fail? (= :fail result)
-         label (if (get-in parent [:rule]) (get-in parent [:rule]) (:comment parent))]
-     (if (not is-fail?)
-       (do
-         (log/debug (str "overh: " (get-in parent [:rule]) " -> " (get-in head [:rule]
-                                                                        (get-in head [:synsem :sem :pred]
-                                                                                "(no pred for head)"))))
-         (log/trace (str "overh successful result: " (strip-refs (dissoc result :dag_unify.core/serialized))))
-         (list result))))))
+    (or (seq? head)
+        (vector? head))
+    (mapcat (fn [child]
+              (overh parent child))
+            head)
+    true
+    ;; TODO: 'true' here assumes that both parent and head are maps: make this assumption explicit,
+    ;; and save 'true' for errors.
+    (let [result (unify (copy parent)
+                        {:head (copy head)})
+
+          is-fail? (= :fail result)]
+      (if (not is-fail?)
+        (list result)))))

 ;; Haskell-looking signature:
 ;; (parent:map) X (child:{set,seq,fs}) => list:map
@@ -82,43 +45,22 @@
 ;; is still true.
 (defn overc [parent comp]
   "add given child as the comp child of the phrase: parent."
-
-  (log/trace (str "set? parent:" (set? parent)))
-  (log/trace (str "seq? parent:" (seq? parent)))
-  (log/trace (str "seq? comp:" (seq? comp)))
-
-  (log/trace (str "type of parent: " (type parent)))
-  (log/trace (str "type of comp  : " (type comp)))
-  (log/trace (str "nil? comp  : " (nil? comp)))
-
   (cond
-   (nil? comp) nil
-
-   (or
-    (seq? parent)
-    (set? parent)
-    (vector? parent))
+   (or (seq? parent)
+       (vector? parent))
    (let [parents (lazy-seq parent)]
      (mapcat (fn [parent]
                (overc parent comp))
              parents))

-   #?(:clj (future? comp))
-   #?(:clj (overc parent (deref comp)))
-
-   (or (set? comp)
-       (vector? comp))
-   (do (log/trace "comp is a set: converting to a seq.")
-       (overc parent (lazy-seq comp)))
+   (vector? comp)
+   (overc parent (lazy-seq comp))

    (seq? comp)
    (let [comp-children comp]
-     (log/trace (str "comp is a seq - actual type is " (type comp)))
-     (filter (fn [result]
-               (not (fail? result)))
-             (mapcat (fn [child]
-                       (overc parent child))
-                     comp-children)))
+     (mapcat (fn [child]
+               (overc parent child))
+             comp-children))
    true
    (let [result (unifyc parent
                         {:comp comp})
@@ -141,78 +83,23 @@
 ;; 2) called with both a child1 and a child2, but child2's supplied value is nil:
 ;;    should be treated the same as empty list.
 (defn over [parents child1 & [child2]]
-  (log/trace (str "over:" (count parents)))
-  (cond (vector? child1)
-        (over parents (seq child1) child2)
-
-        (vector? child2)
-        (over parents child1 (seq child2))
-
-        (map? parents)
-        (do
-          (log/trace (str "parents is a map: converting to a list and re-calling."))
-          (over (list parents) child1 child2))
-
-        (nil? child2)
-        (over parents child1 :top)
-
-        (empty? parents)
-        nil
-
-        (and (map? parents)
-             (not (nil? (:dag_unify.core/serialized parents))))
-        ;; In this case, supposed 'parent' is really a lexical item: for now, definition of 'lexical item' is,
-        ;; it has a non-nil value for :dag_unify.core/serialized - just return nil, nothing else to do.
-        ;; TODO: above test of 'lexical item' is not right: a parent might very well have a :serialized key.
-        (throw (exception (str "Don't know what to do with this parent: " parents)))
-
-        ;; if parent is a symbol, evaluate it; should evaluate to a list of expansions (which might also be symbols, etc).
-        #?(:clj (symbol? parents))
-        #?(:clj (over (eval parents) child1 child2))
+  (cond (map? parents)
+        (over (list parents) child1 child2)

         true
-        (let [parent (first parents)] ;; TODO: use recur
-          (cond
-            (nil? (get-in parent [:schema-symbol] nil))
-            (throw (exception (str "no schema symbol for parent: " (:rule parent))))
-
-            (nil? (:first parent))
-            (throw (exception (str "no :first key for parent: " (:rule parent) " : should be set to either :head or :comp.")))
-
-            (and (not (= :head (:first parent)))
-                 (not (= :comp (:first parent))))
-            (throw (exception (str ":first key for parent: " (:rule parent) " : must be either :head or :comp, but it was: " (:first parent))))
-
-            true
-            (let [[head comp] (if (= (:first parent) :head)
-                                [child1 child2]
-                                [child2 child1])]
-              (log/trace (str "over: parent: " (get-in parent [:rule]) " (" (get-in parent [:schema-symbol]) "); heads:["
-                              (string/join ","
-                                           (map (fn [h]
-                                                  (get-in h [:rule]
-                                                          (str (get-in h [:synsem :sem :pred]))))
-                                                head))
-                              "]"))
-              (if (= (:first parent) :head)
-                ;; else, head is left child.
-                (do (log/trace "over: left child (head):" (strip-refs child1))
-                    (log/trace "over: right child (comp):" (strip-refs child2)))
-                ;; else, head is right child.
-                (do (log/trace "over: left child (comp):" (strip-refs child1))
-                    (log/trace "over: right child (head):" (strip-refs child2))))
-
-              (concat
-               ;; if parent is map, do introspection: figure out the schema from the :schema-symbol attribute,
-               ;; and figure out head-comp ordering from :first attribute.
-               (filter (fn [each]
-                         (not (= :fail each)))
-                       (overhc parent
-                               (if (= (:first parent) :head)
-                                 child1 child2)
-                               (if (= (:first parent) :head)
-                                 child2 child1)))
-               (over (rest parents) child1 child2)))))))
+        (mapcat
+         (fn [parent]
+           (let [[head comp] (if (= (:first parent) :head)
+                               [child1 child2]
+                               [child2 child1])]
+             (filter (fn [each]
+                       (not (= :fail each)))
+                     (overhc parent
+                             (if (= (:first parent) :head)
+                               child1 child2)
+                             (if (= (:first parent) :head)
+                               child2 child1)))))
+         parents)))

 (defn morph-with-recovery [morph-fn input]
   (if (nil? input)


Fix broken auth test

Fix broken auth test

--- test/time_tracker/auth/core_test.clj
+++ test/time_tracker/auth/core_test.clj
@@ -59,7 +59,7 @@
 (deftest wrap-google-authenticated
   (let [handler (fn [request]
                   (res/response "Here is your response. Share it with all your friends."))
-        wrapped-handler (auth/wrap-google-authenticated ["test" "test2"] handler)
+        wrapped-handler (auth/wrap-google-authenticated handler ["test" "test2"])
         user-creds {:aud "test"
                     :username "sandy"}]


Add :conflicting to route data spec

Add :conflicting to route data spec

--- modules/reitit-core/src/reitit/spec.cljc
+++ modules/reitit-core/src/reitit/spec.cljc
@@ -40,7 +40,9 @@
 (s/def ::name keyword?)
 (s/def ::handler fn?)
 (s/def ::no-doc boolean?)
-(s/def ::default-data (s/keys :opt-un [::name ::handler ::no-doc]))
+(s/def ::conflicting boolean?)
+(s/def ::default-data
+  (s/keys :opt-un [::name ::handler ::no-doc ::conflicting]))

 ;;
 ;; router


Remove dead code

Remove dead code

--- modules/reitit-core/src/reitit/trie.cljc
+++ modules/reitit-core/src/reitit/trie.cljc
@@ -116,23 +116,10 @@
           (update :children dissoc ""))
       node')))

-(defn decode!
-  ([path start end]
-    #?(:clj  (let [s (subs path start end)]
-               (if (str/index-of s \%)
-                 (URLDecoder/decode
-                   (if (str/index-of s \+) (.replace ^String s "+" "%2B") s)
-                   "UTF-8")
-                 s))
-       :cljs (js/decodeURIComponent (subs path start end))))
-  ([path start end percent? plus?]
-    #?(:clj  (let [s (String. ^chars path ^int start ^int (- end start))]
-               (if percent?
-                 (URLDecoder/decode
-                   (if plus? (.replace ^String s "+" "%2B") s)
-                   "UTF-8")
-                 s))
-       :cljs (js/decodeURIComponent (subs path start end)))))
+#?(:cljs
+   (defn decode! [path start end percent?]
+     (let [path (subs path start end)]
+       (if percent? (js/decodeURIComponent path) path))))

 (defn data-matcher [data]
   #?(:clj  (Trie/dataMatcher data)
@@ -163,17 +150,16 @@
      :cljs (reify Matcher
              (match [_ i max path]
                (if (and (< i max) (not= (get path i) \/))
-                 (loop [percent? false, plus? false, j i]
+                 (loop [percent? false, j i]
                    (if (= max j)
                      (if-let [match (match matcher max max path)]
-                       (-assoc! match key (decode! path i max percent? plus?)))
+                       (-assoc! match key (decode! path i max percent?)))
                      (let [c ^char (get path j)]
                        (case c
                          \/ (if-let [match (match matcher j max path)]
-                              (-assoc! match key (decode! path i j percent? plus?)))
-                         \% (recur true plus? (inc j))
-                         \+ (recur percent? true (inc j))
-                         (recur percent? plus? (inc j))))))))
+                              (-assoc! match key (decode! path i j percent?)))
+                         \% (recur true (inc j))
+                         (recur percent? (inc j))))))))
              (view [_] [key (view matcher)])
              (depth [_] (inc (depth matcher))))))

@@ -182,8 +168,7 @@
      :cljs (let [match (->Match data nil)]
              (reify Matcher
                (match [_ i max path]
-                 (if (< i max)
-                   (-assoc! match key (decode! path i max))))
+                 (if (< i max) (-assoc! match key (decode! path i max true))))
                (view [_] [key [data]])
                (depth [_] 1)))))


Refactored functional tests and added a new one.

- Accomodate changes to rates and taxes data.
- Use literals for test data and keep the data local to each assertion.
- Add test to check if rates are provided for all users.

--- test/time_tracker/invoices/functional_test.clj
+++ test/time_tracker/invoices/functional_test.clj
@@ -59,46 +59,101 @@
         [ws-chan socket]      (test-helpers/make-ws-connection "gid1")
         created-timer         (create-timer-over-ws ws-chan socket
                                                     project-id current-time
-                                                    3600)
-        data                  {:start (- current-time (* 60 60 24))
-                               :end current-time
-                               :address "baz"
-                               :notes "quux"
-                               :user-id->rate (zipmap user-ids
-                                                      [12 21])
-                               :utc-offset 330
-                               :currency :inr}]
+                                                    3600)]
     (try
       (testing "Existing client"
-        (let [{:keys [status]} (test-helpers/http-request-raw
+        (let [data             {:client "foo"
+                                :start (- current-time (* 60 60 24))
+                                :end current-time
+                                :address "baz"
+                                :notes "quux"
+                                :user-id->rate (vec (for [user-id user-ids]
+                                                      {:user-id user-id
+                                                       :rate    5}))
+                                :utc-offset 330
+                                :currency :inr
+                                :tax-rates nil}
+              {:keys [status]} (test-helpers/http-request-raw
                                  :post
                                  invoice-url
                                  "gid1"
-                                 (assoc data :client "foo"))]
+                                 data)]
           (is (= 200 status))))

       (testing "Another client with no timers"
-        (let [{:keys [status body]} (test-helpers/http-request-raw
+        (let [data                  {:client "bar"
+                                     :start (- current-time (* 60 60 24))
+                                     :end current-time
+                                     :address "baz"
+                                     :notes "quux"
+                                     :user-id->rate (vec (for [user-id user-ids]
+                                                           {:user-id user-id
+                                                            :rate    5}))
+                                     :utc-offset 330
+                                     :currency :inr
+                                     :tax-rates nil}
+              {:keys [status body]} (test-helpers/http-request-raw
                                       :post
                                       invoice-url
                                       "gid1"
-                                      (assoc data :client "bar"))]
+                                      data)]
           (is (= 200 status))))
-
+
       (testing "Client does not exist"
-        (let [{:keys [status body]} (test-helpers/http-request-raw
+        (let [data                  {:client "quux"
+                                     :start (- current-time (* 60 60 24))
+                                     :end current-time
+                                     :address "baz"
+                                     :notes "quux"
+                                     :user-id->rate (vec (for [user-id user-ids]
+                                                           {:user-id user-id
+                                                            :rate    5}))
+                                     :utc-offset 330
+                                     :currency :inr
+                                     :tax-rates nil}
+              {:keys [status body]} (test-helpers/http-request-raw
+                                     :post
+                                     invoice-url
+                                     "gid1"
+                                     data)]
+          (is (= 404 status))))
+
+      (testing "Invalid args"
+        (let [data                  {:client "foo"
+                                     :start (- current-time (* 60 60 24))
+                                     :end current-time
+                                     :address "baz"
+                                     :notes "quux"
+                                     :user-id->rate (vec (for [user-id user-ids]
+                                                           {:user-id user-id
+                                                            :rate    5}))
+                                     :utc-offset "midget"
+                                     :currency :inr
+                                     :tax-rates nil}
+              {:keys [status body]} (test-helpers/http-request-raw
                                       :post
                                       invoice-url
                                       "gid1"
-                                      (assoc data :client "quux"))]
-          (is (= 404 status))))
+                                      data)]
+          (is (= 400 status))))

-      (testing "Invalid args"
-        (let [{:keys [status body]} (test-helpers/http-request-raw
+      (testing "Insufficient user rates"
+        (let [user-id (first user-ids)
+              data    {:client "foo"
+                       :start (- current-time (* 60 60 24))
+                       :end current-time
+                       :address "baz"
+                       :notes "quux"
+                       :user-id->rate [{:user-id user-id
+                                        :rate    3}]
+                       :utc-offset 330
+                       :currency :inr
+                       :tax-rates nil}
+              {:keys [status body]} (test-helpers/http-request-raw
                                       :post
                                       invoice-url
                                       "gid1"
-                                      (assoc data :utc-offset "midget"))]
+                                      data)]
           (is (= 400 status))))

       (finally (ws/close socket)))))


Used wrong key in ack message

Used wrong key in ack message

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -414,7 +414,7 @@
   (if ((:short-circuitable? messenger) channel)
     (ack-segment-short-circuit (lookup-channels messenger acker-id) ack)
     (let [pub-man (get-publication messenger conn-info)]
-      (let [buf (protocol/build-acker-message acker-id (:acker-id ack) (:completion-id ack) (:ack-val ack))]
+      (let [buf (protocol/build-acker-message acker-id (:id ack) (:completion-id ack) (:ack-val ack))]
         (pubm/write pub-man buf 0 protocol/ack-msg-length)))))

 (defmethod extensions/internal-ack-segments AeronConnection


Fix handling of publications in gc-publications

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -190,7 +190,7 @@

 ;; FIXME: gc'ing publications could be racy if a publication is grabbed
 ;; just as it is being gc'd - though it is unlikely
-(defn gc-publications [publications connections opts]
+(defn gc-publications [publications opts]
   (let [interval (arg-or-default :onyx.messaging/peer-link-gc-interval opts)
         idle (arg-or-default :onyx.messaging/peer-link-idle-timeout opts)]
     (loop []
@@ -202,10 +202,10 @@
                              (filter (fn [[k v]] (>= (- t ^long @(:last-used v)) idle))
                                      snapshot))]
           (doseq [k to-remove]
-            (let [pub (:publication (snapshot k))
-                  conn (@connections k)]
+            (let [pub-manager (:publication (snapshot k))
+                  pub (:publication pub-manager)
+                  conn (:connection pub-manager)]
               (swap! publications dissoc k)
-              (swap! connections dissoc k)
               (.close ^Publication pub)
               (.close ^Aeron conn))))
         (catch InterruptedException e
@@ -214,7 +214,7 @@
           (fatal e)))
       (recur))))

-(defrecord AeronPeerGroup [opts publications connections subscribers subscriber-count compress-f decompress-f send-idle-strategy]
+(defrecord AeronPeerGroup [opts publications subscribers subscriber-count compress-f decompress-f send-idle-strategy]
   component/Lifecycle
   (start [component]
     (taoensso.timbre/info "Starting Aeron Peer Group")
@@ -236,12 +236,11 @@
           decompress-f (or (:onyx.messaging/decompress-fn opts) decompress)
           virtual-peers (atom (pm/vpeer-manager))
           publications (atom {})
-          connections (atom {})
           subscriber-count (arg-or-default :onyx.messaging.aeron/subscriber-count opts)
           subscribers (mapv (fn [stream-id]
                               (start-subscriber! bind-addr port stream-id virtual-peers decompress-f receive-idle-strategy))
                             (range subscriber-count))
-          pub-gc-thread (future (gc-publications publications connections opts))]
+          pub-gc-thread (future (gc-publications publications opts))]
       (assoc component
              :pub-gc-thread pub-gc-thread
              :bind-addr bind-addr
@@ -251,7 +250,6 @@
              :media-driver-context media-driver-context
              :media-driver media-driver
              :publications publications
-             :connections connections
              :virtual-peers virtual-peers
              :compress-f compress-f
              :decompress-f decompress-f
@@ -260,7 +258,7 @@
              :subscriber-count subscriber-count
              :subscribers subscribers)))

-  (stop [{:keys [media-driver media-driver-context subscribers publications connections] :as component}]
+  (stop [{:keys [media-driver media-driver-context subscribers publications] :as component}]
     (taoensso.timbre/info "Stopping Aeron Peer Group")
     (future-cancel (:pub-gc-thread component))
     (doseq [subscriber subscribers]


Improved core test layout with testing macro

--- test/compojure/test/core.clj
+++ test/compojure/test/core.clj
@@ -7,61 +7,59 @@
         clout.core)
   (:require [compojure.test-namespace :as testns]))

-(deftest route-with-vector-arguments
-  ((GET "/foo" [x y]
-     (is (= x "bar"))
-     (is (= y "baz"))
-     nil)
-   {:request-method :get
-    :uri "/foo"
-    :params {"x" "bar", "y" "baz"}}))
+(deftest request-destructuring
+  (testing "vector arguments"
+    ((GET "/foo" [x y]
+       (is (= x "bar"))
+       (is (= y "baz"))
+       nil)
+    {:request-method :get
+     :uri "/foo"
+     :params {"x" "bar", "y" "baz"}}))
+
+  (testing "map arguments"
+    ((GET "/foo" {params :params}
+       (is (= (params {:x "a", :y "b"})))
+       nil)
+    {:request-method :get
+     :uri "/foo"
+     :params {"x" "a", "y" "b"}})))

-(deftest route-with-map-arguments
-  ((GET "/foo" {params :params}
-     (is (= (params {:x "a", :y "b"})))
-     nil)
-   {:request-method :get
-    :uri "/foo"
-    :params {"x" "a", "y" "b"}}))
+(deftest route-matching
+  (testing "_method parameter"
+    (let [req  {:request-method :post
+                :form-params {"_method" "PUT"}
+                :uri "/foo"}
+          resp {:status 200, :headers {}, :body "bar"}
+          route (PUT "/foo" [] resp)]
+      (is (= (route req) resp))))

-(deftest route-with-method-param
-  (let [req  {:request-method :post
-              :form-params {"_method" "PUT"}
-              :uri "/foo"}
-        resp {:status 200, :headers {}, :body "bar"}
-        route (PUT "/foo" [] resp)]
-    (is (= (route req) resp))))
+  (testing "custom regexes"
+    (expect [route-compile
+              (has-args ["/foo/:id" {:id "[0-9]+"}]
+                (times 1))]
+      (eval `(GET ["/foo/:id" :id "[0-9]+"] [])))))

-(deftest route-with-custom-regexes
-  (expect [route-compile
-             (has-args ["/foo/:id" {:id "[0-9]+"}]
-               (times 1))]
-    (eval `(GET ["/foo/:id" :id "[0-9]+"] []))))
+(deftest wrap
+  (testing "wrap function"
+    (defn func1 [x] (inc x))
+    (let [wrapper (fn [f] (fn [x] (f (inc x))))]
+      (wrap! func1 wrapper)
+      (is (= (func1 3) 5))))

-(defn func1 [x] (inc x))
+  (testing "wrap keyword"
+    (defn func2 [x] (inc x))
+    (defn wrap-test1 [f]
+      (fn [x] (f (* 2 x))))
+    (wrap! func2 :test1)
+    (is (= (func2 3) 7)))

-(deftest wrap-var-with-funcion
-  (let [wrapper (fn [f] (fn [x] (f (inc x))))]
-    (wrap! func1 wrapper)
-    (is (= (func1 3) 5))))
+  (testing "wrap namespaced keyword"
+    (defn func3 [x] (inc x))
+    (wrap! func3 :testns/test2)
+    (is (= (func3 3) 10)))

-(defn func2 [x] (inc x))
-
-(defn wrap-test1 [f]
-  (fn [x] (f (* 2 x))))
-
-(deftest wrap-var-with-keyword
-  (wrap! func2 :test1)
-  (is (= (func2 3) 7)))
-
-(defn func3 [x] (inc x))
-
-(deftest wrap-var-with-namespaced-keyword
-  (wrap! func3 :testns/test2)
-  (is (= (func3 3) 10)))
-
-(defn func4 [x] (inc x))
-
-(deftest wrap-var-with-function-and-keyword
-  (wrap! func4 wrap-test1 :test1)
-  (is (= (func4 3) 13)))
+  (testing "wrap function and keyword"
+    (defn func4 [x] (inc x))
+    (wrap! func4 wrap-test1 :test1)
+    (is (= (func4 3) 13))))


Fix tests

Fix tests

--- modules/reitit-ring/src/reitit/ring.cljc
+++ modules/reitit-ring/src/reitit/ring.cljc
@@ -18,30 +18,31 @@
   "Creates a ring-handler out of a ring-router.
   Supports both 1 (sync) and 3 (async) arities."
   [router]
-  (with-meta
-    (fn
-      ([request]
-       (if-let [match (r/match-by-path router (:uri request))]
-         (let [method (:request-method request :any)
-               params (:params match)
-               result (:result match)
-               handler (or (-> result method :handler)
-                           (-> result :any :handler))
-               request (cond-> (impl/fast-assoc request ::match match)
-                               (seq params) (impl/fast-assoc :path-params params))]
-           (handler request))))
-      ([request respond raise]
-       (if-let [match (r/match-by-path router (:uri request))]
-         (let [method (:request-method request :any)
-               params (:params match)
-               result (:result match)
-               handler (or (-> result method :handler)
-                           (-> result :any :handler))
-               request (cond-> (impl/fast-assoc request ::match match)
-                               (seq params) (impl/fast-assoc :path-params params))]
-           (handler request respond raise))
-         (respond nil))))
-    {::router router}))
+  (let [default-handler (constantly nil)]
+    (with-meta
+      (fn
+        ([request]
+         (if-let [match (r/match-by-path router (:uri request))]
+           (let [method (:request-method request :any)
+                 params (:params match)
+                 result (:result match)
+                 handler (or (-> result method :handler)
+                             (-> result :any (:handler default-handler)))
+                 request (cond-> (impl/fast-assoc request ::match match)
+                                 (seq params) (impl/fast-assoc :path-params params))]
+             (handler request))))
+        ([request respond raise]
+         (if-let [match (r/match-by-path router (:uri request))]
+           (let [method (:request-method request :any)
+                 params (:params match)
+                 result (:result match)
+                 handler (or (-> result method :handler)
+                             (-> result :any (:handler default-handler)))
+                 request (cond-> (impl/fast-assoc request ::match match)
+                                 (seq params) (impl/fast-assoc :path-params params))]
+             (handler request respond raise))
+           (respond nil))))
+      {::router router})))

 (defn get-router [handler]
   (some-> handler meta ::router))


Allow optional msg-fn callback/filter for fenced-pump.

--- src/cbfg/fence.cljs
+++ src/cbfg/fence.cljs
@@ -35,7 +35,8 @@
 ;; request format
 ;; {:rq function-to-call :fence true-or-false}

-(defn make-fenced-pump [actx name in-ch out-ch max-inflight close?]
+(defn make-fenced-pump [actx name in-ch out-ch max-inflight close? &
+                        {:keys [msg-fn] :or {msg-fn identity}}]
   (act-loop fenced-pump actx
    [name name
     inflight-chs #{}                ; chans of requests currently being processed.
@@ -46,7 +47,8 @@
                     inflight-chs    ; then ignore in-ch & finish any inflight requests.
                     (conj inflight-chs in-ch)))]
      (if (seq chs)                  ; empty when in-ch is closed and no inflight-chs.
-       (let [[v ch] (aalts fenced-pump chs)]
+       (let [[v ch] (aalts fenced-pump chs)
+             v (msg-fn v)]
          (cond
           (= ch in-ch) (if (nil? v)
                          (recur name inflight-chs out-ch nil) ; using out-ch as sentinel.


Fix cdsStart/End type.

Fix cdsStart/End type.

--- src/cgdata/core.clj
+++ src/cgdata/core.clj
@@ -505,8 +505,8 @@
    :chrom :category
    :txStart :float
    :txEnd :float
-   :cdsStart :category
-   :cdsEnd :category
+   :cdsStart :float
+   :cdsEnd :float
    :exonCount :float
    :exonStarts :category
    :exonEnds :category


Make tests more consistent

Make tests more consistent

--- test/expound/alpha_test.cljc
+++ test/expound/alpha_test.cljc
@@ -3754,8 +3754,11 @@
 ;; is merged
 #?(:clj
    (deftest ring-specs
-     (is (=
-          "-- Spec failed --------------------
+     (let [actual (expound/expound-str
+           :ring.sync+async/handler (fn handler [req] {})
+           {:print-specs? false})]
+       (is (or (=
+                "-- Spec failed --------------------

   expound.alpha-test/fn/fn/handler

@@ -3780,38 +3783,94 @@
 -------------------------
 Detected 1 error
 "
-          (expound/expound-str
-           :ring.sync+async/handler (fn handler [req] {})
-           {:print-specs? false})))
-     (is (=
-          "-- Spec failed --------------------
+                actual)
+               (=
+                "-- Spec failed --------------------

   expound.alpha-test/fn/handler

-when conformed as
-
-  :sync
-
-should satisfy
-
-  map?
-
-or
-
 returned an invalid value

-  [:sync {:status 200, :headers {}}]
-
-should satisfy
-
-  map?
+  {}
+
+should contain keys: :headers, :status
+
+|      key |                                          spec |
+|----------+-----------------------------------------------|
+| :headers |                        :ring.response/headers |
+|  :status | (and int? (fn [%] (int-in-range? 100 600 %))) |

 -------------------------
 Detected 1 error
 "
-          (expound/expound-str
-           :ring.sync+async/handler
-           (fn handler [req]
-             {:status 200
-              :headers {}})
-           {:print-specs? false})))))
+                actual)
+               )
+           (str "Actual message was:\n" actual "\nand expected was:\n" "-- Spec failed --------------------
+
+  expound.alpha-test/fn/fn/handler
+
+returned an invalid value
+
+  {}
+
+should contain keys: :headers, :status
+
+|      key |                                          spec |
+|----------+-----------------------------------------------|
+| :headers |                        :ring.response/headers |
+|  :status | (and int? (fn [%] (int-in-range? 100 600 %))) |
+
+-------------------------
+Detected 1 error
+")))
+     (let [actual (expound/expound-str
+                   :ring.sync+async/handler
+                   (fn handler [req]
+                     {:status 200
+                      :headers {}})
+                   {:print-specs? false})]
+       (is
+        (or
+         (= "-- Spec failed --------------------
+
+  expound.alpha-test/fn/handler
+
+when conformed as
+
+  :sync
+
+should satisfy
+
+  map?
+
+or
+
+returned an invalid value
+
+  [:sync {:status 200, :headers {}}]
+
+should satisfy
+
+  map?
+
+-------------------------
+Detected 1 error
+"
+            actual)
+         (re-matches
+          #"-- Exception ----------------------
+
+  expound.alpha-test/fn/handler
+
+threw exception
+
+  \"Wrong number of args \(3\) passed to: .*\"
+
+with args:
+
+  \{:server-port 1, :server-name \"\", :remote-addr \"\", :uri \"/\", :scheme :http, :protocol \"HTTP/1.1\", :headers \{\}, :request-method :a\}, .*, .*
+
+-------------------------
+Detected 1 error
+"
+          actual))))))


Add some comments to fastq module.

Add some comments to fastq module.

--- src/cljam/fastq.clj
+++ src/cljam/fastq.clj
@@ -42,7 +42,8 @@

 (defrecord FASTQRead [^String name ^String sequence quality])

-(defn- ^FASTQRead decode-fastq
+(defn- ^FASTQRead deserialize-fastq
+  "Deserialize a read from 4 lines of fastq file."
   [[^String name-line ^String seq-line ^String plus-line ^String qual-line]
    & {:keys [decode-quality] :or {decode-quality :phred33}}]
   {:pre [(not-empty name-line)
@@ -69,15 +70,17 @@
      qual-line)))

 (defn read-sequence
+  "Returns a lazy sequence of FASTQReads deserialized from given reader."
   [^FASTQReader rdr & opts]
   (sequence
    (comp (map string/trim)
          (partition-all 4)
-         (map #(apply decode-fastq % opts)))
+         (map #(apply deserialize-fastq % opts)))
    (line-seq (.reader rdr))))

-(defn- ^String encode-fastq
-  [{:keys [name sequence quality]}
+(defn- ^String serialize-fastq
+  "Serialize a FASTQRead to FASTQ format string."
+  [^FASTQRead {:keys [name sequence quality]}
    & {:keys [encode-quality] :or {encode-quality :phred33}}]
   {:pre [(not-empty name)
          (not-empty sequence)
@@ -99,7 +102,8 @@
       (as-> x (apply str x))))

 (defn write-sequence
+  "Write given sequence of reads to a FASTQ file."
   [^FASTQWriter wtr sequence & opts]
   (let [w ^java.io.Writer (.writer wtr)]
     (doseq [s sequence]
-      (.write w ^String (apply encode-fastq s opts)))))
+      (.write w ^String (apply serialize-fastq s opts)))))


Remove unnecessary parens

Remove unnecessary parens

--- common/clojure/nightweb/torrents_dht.clj
+++ common/clojure/nightweb/torrents_dht.clj
@@ -98,9 +98,9 @@
              (not (c/is-me? their-hash-bytes true))
              (-> (for [my-user-hash @c/my-hash-list]
                    (db/get-fav-data {:ptrhash their-hash-bytes} my-user-hash))
-                 (doall)
-                 (flatten)
-                 (count)
+                 doall
+                 flatten
+                 count
                  (= 0)))
     (let [^String their-hash-str (f/base32-encode their-hash-bytes)
           user-dir (c/get-user-dir their-hash-str)]
@@ -121,11 +121,11 @@
   (when (or (c/is-me? user-hash true)
             (->> (for [my-user-hash @c/my-hash-list]
                    (db/get-single-fav-data {:userhash user-hash} my-user-hash))
-                 (doall)
+                 doall
                  (filter #(= 1 (:status %)))
-                 (count)
+                 count
                  (= 0)
-                 (not)))
+                 not))
     (case status
       ; if the fav has a status of 0, unfollow them if necessary
       0 (remove-user-hash ptr-hash)


working datastore writer

working datastore writer

--- src/datasplash/datastore.clj
+++ src/datasplash/datastore.clj
@@ -5,12 +5,10 @@
            [com.google.cloud.dataflow.sdk.values PBegin PCollection]))

 (defn write-datastore-raw
-  [{:keys [dataset host] :as options} p]
+  [{:keys [dataset host] :as options} pcoll]
   (let [opts (assoc options :label :write-datastore)
         ptrans (-> (DatastoreIO/sink)
-                   (.withDataset dataset)
+                   (.withDataset (name dataset))
                    (cond-> host (.withHost host))
                    (Write/to))]
-    (-> p
-        (cond-> (instance? Pipeline p) (PBegin/in))
-        (apply-transform ptrans named-schema opts))))
+    (apply-transform pcoll ptrans named-schema opts)))


Refactor code

Refactor code

--- src/day8/re_frame/trace.cljs
+++ src/day8/re_frame/trace.cljs
@@ -137,7 +137,7 @@
                                nil)}])))

 (defn query->fn [query]
-  (if (= "contains" (:filter-type query))
+  (if (= :contains (:filter-type query))
     (fn [trace]
       (str/includes? (str/lower-case (str (:operation trace) " " (:op-type trace)))
                     (:query query)))
@@ -150,7 +150,6 @@
       (let [padding   {:padding "0px 5px 0px 5px"}
             row-style (merge padding {:border-top (case op-type :event "1px solid lightgrey" nil)})
             #_#__ (js/console.log (devtools/header-api-call tags))]
-
         (list [:tr {:key   id
                     :style {:color (case op-type
                                      :sub/create "green"
@@ -172,21 +171,17 @@
                 [:tr {:key (str id "-details")}
                  [:td {:col-span 3} (with-out-str (pprint/pprint (dissoc tags :query-v :event :duration)))]]))))))

-(defonce app-state [:traces {:filter-input ""
-                             :filter-items []}]) ;; [{:id (random-uuid) :query "showing" :filter-type "contains"} {:id (random-uuid) :query "Reagent" :filter-type "contains"}
-
 (defn render-trace-panel []
   (let [filter-input     (r/atom "")
         filter-items     (r/atom [])
-        filter-type      (r/atom "contains")]
+        filter-type      (r/atom :contains)]
     (fn []
       (let [showing-traces       (if (= @filter-items [])
                                    @traces
                                    (filter (apply every-pred (map query->fn @filter-items)) @traces))
             save-query           (fn [_]
-                                   (println @filter-type @filter-input)
                                    (swap! filter-items conj {:id (random-uuid)
-                                                             :query (if (= @filter-type "contains")
+                                                             :query (if (= @filter-type :contains)
                                                                       (str/lower-case @filter-input)
                                                                       (js/parseInt @filter-input))
                                                              :filter-type @filter-type}))]
@@ -195,19 +190,15 @@
            [:div.filter-control-input
             {:style {:margin-bottom 10}}
             [:select {:value @filter-type :on-change (fn [e]
-                                                         (reset! filter-type (.. e -target -value))
-                                                         (println (.. e -target -value)))}
-             [:option "contains"]
-             [:option "slower than"]]
+                                                         (reset! filter-type
+                                                                 (keyword (str/replace (.. e -target -value) " " "-"))))}
+             [:option :contains]
+             [:option :slower-than]]
             [search-input {:on-save save-query
                            :on-change #(reset! filter-input (.. % -target -value))}]
             [:button.button.icon-button {:on-click save-query
                                          :style {:margin 0}}
              [components/icon-add]]
-            ;; [:button {:style {:background "#aae0ec"
-            ;;                   :padding 7
-            ;;                   :margin 5}}
-            ;;  "-"]]
             [:br]]
            [:ul.filter-items
              (map (fn [item]


Add fn which scrolls down divs

Add fn which scrolls down divs

--- src/discuss/utils/views.cljs
+++ src/discuss/utils/views.cljs
@@ -1,17 +1,20 @@
 (ns discuss.utils.views
-  (:require [goog.string :as gstring]
+  (:require [goog.dom :as gdom]
+            [goog.string :as gstring]
             [om.core :as om :include-macros true]
-            [om.dom :as dom :include-macros true]))
+            [om.dom :as dom :include-macros true]
+            [discuss.utils.extensions]
+            [discuss.utils.common :as lib]))

 (defn fa-icon
   "Wrapper for font-awesome icons."
   ([class]
    (dom/i #js {:react-key (discuss.utils.common/get-unique-key)
-               :key (discuss.utils.common/get-unique-key)
+               :key       (discuss.utils.common/get-unique-key)
                :className (str "fa " class)}))
   ([class f]
    (dom/i #js {:react-key (discuss.utils.common/get-unique-key)
-               :key (discuss.utils.common/get-unique-key)
+               :key       (discuss.utils.common/get-unique-key)
                :className (str "pointer fa " class)
                :onClick   f})))

@@ -69,4 +72,10 @@
   [content]
   (dom/div #js {:className "panel panel-default"}
            (dom/div #js {:className "panel-body"}
-                    content)))+                    content)))
+
+(defn scroll-divs-to-bottom
+  "Align divs to bottom. Scrolls down the complete content of each div."
+  [class]
+  (let [divs (gdom/getElementsByClass (lib/prefix-name class))]
+    (doall (map #(set! (.. % -scrollTop) (.. % -scrollHeight)) divs))))


cleaup progress

cleaup progress

--- src/cljs/swarmpit/component/progress.cljs
+++ src/cljs/swarmpit/component/progress.cljs
@@ -1,41 +1,16 @@
 (ns swarmpit.component.progress
   (:require [material.component :as comp]
-            [material.component.form :as form]
+            [sablono.core :refer-macros [html]]
             [rum.core :as rum]))

 (enable-console-print!)

-(def progress-style
-  {:background "rgba(0, 0, 0, .2)"
-   :position   "absolute"
-   :display    "table"
-   :textAlign  "center"
-   :top        0
-   :left       0
-   :height     "100%"
-   :width      "100%"
-   :zIndex     10000})
-
-(def progress-inner-style
-  {:display       "table-cell"
-   :verticalAlign "middle"})
-
-(rum/defc progress < rum/static []
-  (comp/mui
-    (comp/circular-progress
-      {:color      "#fff"
-       :size       80
-       :thickness  8
-       :style      progress-style
-       :innerStyle progress-inner-style})))
-
 (rum/defc form < rum/static [loading? comp]
   (if loading?
-    (progress)
-    comp))
-
-(rum/defc loading < rum/static []
-  (form/loading true))
-
-(rum/defc loaded < rum/static []
-  (form/loading false))+    (html
+      [:div {:style {:width          "100%"
+                     :height         "100vh"
+                     :display        "flex"
+                     :alignItems     "center"
+                     :justifyContent "center"}}
+       [:div {:style {:maxWidth "50%"}} (comp/circular-progress {:size 100})]]) comp))


Solaris fixups

Solaris fixups

--- config/software/libxslt.clj
+++ config/software/libxslt.clj
@@ -27,4 +27,10 @@
                    :args ["--prefix=/opt/opscode/embedded" "--with-libxml-prefix=/opt/opscode/embedded"
                           "--with-libxml-include-prefix=/opt/opscode/embedded/include"
                           "--with-libxml-libs-prefix=/opt/opscode/embedded/lib"]}
+                  {:command (if (is-os? "solaris2") "perl" "true")
+                   :args [ "-pi" "-e" "s/^(LIBXSLT_VERSION_SCRIPT = \$.+)$/\# Woof/g"
+                           (str *omnibus-build-dir* "/libxslt-1.1.26/libxslt/Makefile") ]}
+                  {:command (if (is-os? "solaris2") "perl" "true")
+                   :args [ "-pi" "-e" "s/^#LIBXSLT_VERSION_SCRIPT.+)$/LIBXSLT_VERSION_SCRIPT =/g"
+                           (str *omnibus-build-dir* "/libxslt-1.1.26/libxslt/Makefile") ]}
                   {:command "make" :args ["install"]}])


Fixed wrong module alias

Fixed wrong module alias

--- src/emender_jenkins/core.clj
+++ src/emender_jenkins/core.clj
@@ -25,7 +25,7 @@
 (require '[emender-jenkins.middleware       :as middleware])
 (require '[emender-jenkins.process-info     :as process-info])
 (require '[emender-jenkins.job-data-fetcher :as job-data-fetcher])
-(require '[emender-jenkins.irc-bot          :as job-data-fetcher])
+(require '[emender-jenkins.irc-bot          :as irc-bot])

 (def cli-options
     "Definitions of all command line options that are  currenty supported."


chore(lein): removed paredit.clj/project.clj

--- paredit.clj/project.clj
+++ paredit.clj/project.clj
@@ -1,45 +0,0 @@
-(defproject org.lpetit/paredit.clj "0.20.0-SNAPSHOT"
-  :description "paredit in clojure, tailored for clojure"
-  :license {:name "Eclipse Public License - v 1.0"
-            :url "http://www.eclipse.org/legal/epl-v10.html"
-            :distribution :repo
-            :comments "same as Clojure"}
-  :dependencies [[org.clojure/clojure           "1.5.1"]
-                 [org.clojure/core.incubator "0.1.1"]
-                 [org.lpetit/net.cgrand.parsley "0.0.12.STABLE001"]
-                 [org.lpetit/net.cgrand.regex   "0.0.4.STABLE001"]]
-  :warn-on-reflection true)
-  #_:manifest #_{"Project-awesome-level" "super-great"
-             ;; function values will be called with the project as an argument.
-             "Class-Path" ~#(clojure.string/join
-                             \space
-                             (leiningen.core.classpath/get-classpath %))
-             ;; symbol values will be resolved to find a function to call.
-             "Grunge-level" my.plugin/calculate-grunginess}
-;:manifest {
-;"Bundle-ManifestVersion" "2"
-;"Bundle-Name" Regex
-;Bundle-SymbolicName: net.cgrand.regex;singleton:=true
-;Bundle-Version: 0.0.4.STABLE001
-;Bundle-ClassPath: .,
-; classes/
-;Bundle-ActivationPolicy: lazy
-;Bundle-Vendor: Christophe Grand
-;Bundle-RequiredExecutionEnvironment: J2SE-1.5
-;Export-Package: net.cgrand
-;Import-Package: clojure;version="1.3.0",
-; clojure.asm;version="1.3.0",
-; clojure.asm.commons;version="1.3.0",
-; clojure.core;version="1.3.0",
-; clojure.core.protocols;version="1.3.0",
-; clojure.core.proxy$clojure.lang;version="1.3.0",
-; clojure.inspector.proxy$java.lang;version="1.3.0",
-; clojure.inspector.proxy$javax.swing.table;version="1.3.0",
-; clojure.java;version="1.3.0",
-; clojure.java.browse_ui.proxy$java.lang;version="1.3.0",
-; clojure.java.io;version="1.3.0",
-; clojure.lang;version="1.3.0",
-; clojure.pprint.proxy$java.io;version="1.3.0",
-; clojure.repl.proxy$java.io;version="1.3.0",
-; clojure.test;version="1.3.0"
-


Assert router

Assert router

--- src/cylon/user/login.clj
+++ src/cylon/user/login.clj
@@ -40,6 +40,7 @@

   AuthenticationHandshake
   (initiate-authentication-handshake [this req]
+    (assert (:routes @router))
     (if-let [p (path-for (:routes @router) ::login-form)]
       (let [loc (str p (as-query-string {"post_login_redirect" (URLEncoder/encode (uri-with-qs req))}))]
         (debugf "Redirecting to %s" loc)


Problem added - Contain Yourself

Problem added - Contain Yourself

--- src/foreclojure/data_set.clj
+++ src/foreclojure/data_set.clj
@@ -470,4 +470,15 @@
               :tests ["(= 3 ((__ nth) 2 [1 2 3 4 5]))"
                       "(= true ((__ >) 7 8))"
                       "(= 4 ((__ quot) 2 8))"
-                      "(= [1 2 3] ((__ take) [1 2 3 4 5] 3))"]})))+                      "(= [1 2 3] ((__ take) [1 2 3 4 5] 3))"]})
+
+       (insert! :problems
+           {:_id 47
+            :title "Contain Yourself"
+            :times-solved 0
+            :description "The contains? function checks if a KEY is present in a given collection.  This often leads beginner clojurians to use it incorrectly with numerically indexed collections like vectors and lists."
+            :tags ["easy"]
+            :tests ["(contains? #{4 5 6} __)"
+		    "(contains? [1 1 1 1 1] __)"
+		    "(contains? {4 :a 2 :b} __)"
+                    "(not (contains? '(1 2 4) __))"]})))


Support for multi-line test cases

Support for multi-line test cases

--- src/foreclojure/problems.clj
+++ src/foreclojure/problems.clj
@@ -285,7 +285,7 @@

 (def-page problem-submission-page []
   [:div.instructions
-   [:p "Thanks for choosing to submit a problem. Please make sure that you own the rights to the code you are submitting and that you wouldn't mind having us use the code as a 4clojure problem."]]
+   [:p "Thanks for choosing to submit a problem. Please make sure that you own the rights to the code you are submitting and that you wouldn't mind having us use the code as a 4clojure problem.  Once you've submitted your problem, it won't appear on the site until someone from the 4clojure team has had a chance to review it."]]
   (form-to {:id "problem-submission"} [:post "/problems/submit"]
     (hidden-field :author (session/flash-get :author))
     (hidden-field :prob-id (session/flash-get :prob-id))
@@ -298,7 +298,7 @@
     (label :description "Problem Description")
     (text-area {:id "problem-description"} :description  (session/flash-get :description))
     [:br]
-    (label :code-box "Problem test cases. Use two underscores (__) for user input. Multiple tests ought to be on one line each.")
+    (label :code-box "Problem test cases. Use two underscores (__) for user input. Individual tests can span multiple lines, but each test should be separated by a totally blank line.")
     (text-area {:id "code-box" :spellcheck "false"}
                :code (session/flash-get :tests))
     [:p
@@ -323,7 +323,7 @@
                   :description description
                   :tags (re-seq #"\S+" tags)
                   :restricted (re-seq #"\S+" restricted)
-                  :tests (s/split-lines code)
+                  :tests (s/split code #"\r\n\r\n")
                   :user (if (empty? author) user author)
                   :approved false})
         (flash-msg "Thank you for submitting a problem! Be sure to check back to see it posted." "/problems"))
@@ -337,7 +337,7 @@
                    :tags (s/join " " tags)
                    :restricted (s/join " " restricted)
                    :description description
-                   :tests (s/join "\n" tests)}]
+                   :tests (s/join "\r\n\r\n" tests)}]
       (session/flash-put! k v))
     (response/redirect "/problems/submit")))


(maint) Dynamically allocate puppetserver port in integration test

Using port 8140 everywhere makes things start failing when multiple tests are
run on the same machine.

--- test/puppetlabs/puppetdb/integration/fixtures.clj
+++ test/puppetlabs/puppetdb/integration/fixtures.clj
@@ -204,20 +204,23 @@
       (fs/mkdirs functions-dir)
       (fs/copy-dir-into "puppet/lib/puppet/functions/" functions-dir))

-    (write-puppetdb-terminus-config pdb-servers puppetdb-conf terminus-config-overrides))
-
-  (let [services (tk-bootstrap/parse-bootstrap-config! dev-bootstrap-file)
-        tmp-conf (ks/temp-file "puppetserver" ".conf")
-        _ (fs/copy dev-config-file tmp-conf)
-        config (tk-config/load-config (.getPath tmp-conf))]
-    (PuppetServerTestServer. {:hostname "localhost"
-                              :port 8140
-                              :code-dir "target/puppetserver/master-code"
-                              :conf-dir "target/puppetserver/master-conf"}
-                             [(.getPath tmp-conf)
-                              "target/puppetserver/master-conf"
-                              "target/puppetserver/master-code"]
-                             (tkbs/bootstrap-services-with-config services config))))
+    (write-puppetdb-terminus-config pdb-servers puppetdb-conf terminus-config-overrides)
+
+    (let [services (tk-bootstrap/parse-bootstrap-config! dev-bootstrap-file)
+          tmp-conf (ks/temp-file "puppetserver" ".conf")
+          _ (fs/copy dev-config-file tmp-conf)
+          port (svc-utils/open-port-num)
+          config (-> (tk-config/load-config (.getPath tmp-conf))
+                     (merge puppetserver-config-overrides)
+                     (assoc-in [:webserver :ssl-port] port))]
+      (PuppetServerTestServer. {:hostname "localhost"
+                                :port port
+                                :code-dir "target/puppetserver/master-code"
+                                :conf-dir "target/puppetserver/master-conf"}
+                               [(.getPath tmp-conf)
+                                "target/puppetserver/master-conf"
+                                "target/puppetserver/master-code"]
+                               (tkbs/bootstrap-services-with-config services config)))))

 (defn run-puppet-server [pdb-servers config-overrides]
   (run-puppet-server-as "localhost" pdb-servers config-overrides))


Solved 5.16 - Chapter 5: COMPLETED :)

Solved 5.16 - Chapter 5: COMPLETED :)

--- src/fpinscala/strictness_and_laziness.clj
+++ src/fpinscala/strictness_and_laziness.clj
@@ -395,10 +395,11 @@
 (defn scan-right-fpins
   "scanRight from FPINS - FPINS solution translation :)"
   [z f s]
-  (second (fold-right [z (stream-cons z '())]
-              #(let [[x1 x2] %2 b (f % x1)]
-                [b (cons b x2)])
-              s)))
+  (second
+    (fold-right [z (stream-cons z '())]
+                #(let [[x1 x2] %2 b (f % x1)]
+                  [b (cons b x2)])
+                s)))
 ;note though that given Clojure does not support lazy arg evaluation
 ;and I don't know how to mimic them, translation is not necessary lazy
 ;as fpins is