Ignore initial query/mutation path for error stamper

--- test/com/wsscode/pathom/connect/graphql2_test.cljc
+++ test/com/wsscode/pathom/connect/graphql2_test.cljc
@@ -137,7 +137,6 @@
                                              :service.OnboardingEvent/postDate {}
                                              :service.OnboardingEvent/title    {}
                                              :service.interfaces/FeedEvent     {}}})))
-

 (def supposed-resolver nil)


fix accidently committed broken test

fix accidently committed broken test

--- test/clj/lambdacd/event_bus_test.clj
+++ test/clj/lambdacd/event_bus_test.clj
@@ -25,5 +25,5 @@
       (publish ctx :test-messages {:message-number 1})
       (publish ctx :test-messages {:message-number 2})

-      (is (= [{:message-number 1} {:message-number 2}] (slurp-chan-with-size 1 payloads-1)))
+      (is (= [{:message-number 1} {:message-number 2}] (slurp-chan-with-size 2 payloads-1)))
       (is (= [{:message-number 1} {:message-number 2}] (slurp-chan-with-size 2 payloads-2))))))


Test that channel can be returned from request function

--- test/clj_gatling/simulation_test.clj
+++ test/clj_gatling/simulation_test.clj
@@ -112,6 +112,21 @@
   (let [result (run-single-scenario {:name "Test scenario"
                                      :steps [{:name "step"
                                               :request (fn [_] true)}]}
+                                    :concurrency 1)]
+    (is (equal? result [{:name "Test scenario"
+                         :id 0
+                         :start number?
+                         :end number?
+                         :requests [{:name "step"
+                                     :id 0
+                                     :start number?
+                                     :end number?
+                                     :result true}]}]))))
+
+(deftest simulation-with-request-returning-channel-with-boolean
+  (let [result (run-single-scenario {:name "Test scenario"
+                                     :steps [{:name "step"
+                                              :request (fn [_] (go true))}]}
                                     :concurrency 1)]
     (is (equal? result [{:name "Test scenario"
                          :id 0


Close client after test.

Close client after test.

In test client was created but never closed.

--- test/http/async/client/test/cert.clj
+++ test/http/async/client/test/cert.clj
@@ -79,8 +79,8 @@
   (let [ctx (ssl-context :keystore-file ks-file
                          :keystore-password password
                          :certificate-file cert-file
-                         :certificate-alias other-cert-alias)
-        client (create-client :ssl-context ctx)]
-    (is (= AsyncHttpClient (class client)))
-    ;; Make sure client is using the SSLContext we supplied
-    (is (= ctx (.getSSLContext (.getConfig client))))))
+                         :certificate-alias other-cert-alias)]
+    (with-open [client (create-client :ssl-context ctx)]
+      (is (= AsyncHttpClient (class client)))
+      ;; Make sure client is using the SSLContext we supplied
+      (is (= ctx (.getSSLContext (.getConfig client)))))))


Rails on activate

Rails on activate

--- src/fugue/boxes/state.cljs
+++ src/fugue/boxes/state.cljs
@@ -11,9 +11,12 @@
 (defn current-buffer-text [state]
   (get-in state [:files (:active state)]))

+(defn valid-buffer? [state id]
+  (some (partial = id) (flatten (:boxes state))))
+
 (defn activate [state id]
   (-> state
-      (assoc :active id)
+      (assoc :active (if (valid-buffer? state id) id (:active state)))
       (assoc :key-seq [])))

 (defn eval-settings [state]


New function: insert-product

New function: insert-product

--- src/arachnida/db_interface.clj
+++ src/arachnida/db_interface.clj
@@ -22,11 +22,15 @@
         (jdbc/query db ["select id from commits where product=? and repo=? and sha=?"
                              product repo sha]))))

+(defn insert-product
+    [db product-name]
+    (jdbc/insert! db "products" {:name product-name}))
+
 (defn insert-changed-file
     [db commit-id changed-file]
     (jdbc/insert! db "changed_files" {:commit_id commit-id
-                                           :file_name (first changed-file)
-                                           :operation (second changed-file)}))
+                                      :file_name (first changed-file)
+                                      :operation (second changed-file)}))

 (defn insert-branch-for-commit
     [db commit-id branch-name]


fix typo

fix typo

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -427,12 +427,12 @@
                                        :subj {:human true}}}
                         :english {:participle "chatting"
                                   :past "chatted"}}]
-            common ;; intransitive
-            (unify common ;; transitive "chatted with <human>"
-                   {:synsem {:subcat {:2 {:cat :prep
-                                          :sem {:obj {:human true}
-                                                :pred :with}
-                                          :subcat '()}}}}))
+            [common ;; intransitive
+             (unify common ;; transitive "chatted with <human>"
+                    {:synsem {:subcat {:2 {:cat :prep
+                                           :sem {:obj {:human true}
+                                                 :pred :with}
+                                           :subcat '()}}}})])
    "charge" {:synsem {:cat :verb
                       :sem {:pred :caricare}}}


copy change from lexicon-verbcoach to lexicon

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1070,7 +1070,8 @@

    "hit" {:english {:past {:english "hit"
                           :note "past tense"}
-                   :participle "hitting"}
+                    :participle "hitting"
+                    :past-participle "hit"}
           :synsem {:cat :verb
                    :sem {:pred :hit}}}


remove "Juan": not a French name

remove "Juan": not a French name

--- src/babel/francais/lexicon.clj
+++ src/babel/francais/lexicon.clj
@@ -387,13 +387,6 @@
                           :person :3rd
                           :gender :masc}}}

-   "Juan" {:synsem {:sem {:pred :Juan
-                          :human true}
-                    :propernoun true
-                    :agr {:number :sing
-                          :person :3rd
-                          :gender :masc}}}
-
    "la" {:synsem {:cat :noun
                   :pronoun true
                   :reflexive true


s/futuro-stem/future-stem/

s/futuro-stem/future-stem/

--- src/babel/francais/lexicon.clj
+++ src/babel/francais/lexicon.clj
@@ -73,7 +73,7 @@
    (let [common
          {:synsem {:essere false
                    :cat :verb}
-          :français {:futuro-stem "aur"
+          :français {:future-stem "aur"
                      :drop-e true
                      :past-participle "eu"
                      :imperfect-stem "av"
@@ -142,7 +142,7 @@
    (let [common
          {:synsem {:essere false
                    :cat :verb}
-          :français {:futuro-stem "devr"
+          :français {:future-stem "devr"
                      :drop-e true
                      :past-participle "dû"
                      :imperfect-stem "dev"
@@ -289,10 +289,9 @@
    "faire"
       (let [shared-part-of-faire
             {:synsem {:cat :verb}
-             :disable true
              :français {:français "faire"
                         :drop-e false
-                        :passato "fait"
+                        :past-participle "fait"
                         :future-stem "fer"
                         :present {:1sing "fais"
                                   :2sing "fais"
@@ -301,10 +300,10 @@
                                   :2plur "faites"
                                   :3plur "font"}}}]

-     [(merge shared-part-of-faire
-             {:synsem {:pred :do}})
-      (merge shared-part-of-faire
-             {:synsem {:pred :make}})])
+        [(unify shared-part-of-faire
+             {:synsem {:sem {:pred :do}}})
+         (unify shared-part-of-faire
+                {:synsem {:pred :make}})])

    "former" {:synsem {:cat :verb
                      :sem {:pred :form}}}
@@ -317,7 +316,7 @@
                              :subj {:human true}}}}]

    "gérer" {:synsem {:cat :verb
-                    :sem {:pred :manage}}}
+                     :sem {:pred :manage}}}
    "il"
    [{:synsem {:cat :noun
               :pronoun true
@@ -468,7 +467,7 @@
    "peindre" {:français {:boot-stem1 "pein"
                          :boot-stem2 "peign"
                          :passé "peint"
-                         :futuro-stem "paindr"
+                         :future-stem "paindr"
                          :imperfect "peign"}
               :synsem {:cat :verb
                        :sem {:pred :paint}}}
@@ -538,7 +537,7 @@
                     subject-agr (ref :top)]
                 {:synsem {:cat :verb
                           :essere true
-                          :français {:futuro-stem "appell"
+                          :français {:future-stem "appell"
                                      :boot-stem "appell"}
                           :sem {:pred :be-called
                                 :reflexive true
@@ -553,7 +552,8 @@

    "se blesser" (let [subject-semantics (ref {:human true})
                       subject-agr (ref :top)]
-                  {:synsem {:cat :verb
+                  {
+                   :synsem {:cat :verb
                             :essere true
                             :sem {:pred :hurt-oneself
                                   :reflexive true
@@ -564,9 +564,11 @@
                                      :2 {:agr subject-agr
                                          :pronoun true
                                          :reflexive true
-                                         :sem subject-semantics}
-                                     :3 {:cat :adverb
-                                         :sem {:pred :bad}}}}})
+                                         :sem subject-semantics}}}})
+
+   ;; not supported in grammar yet.
+   ;;                                     :3 {:cat :adverb
+   ;;                                         :sem {:pred :bad}}}}})

   "se endormir" (let [subject-semantics (ref {:human true})
                     subject-agr (ref :top)]
@@ -602,7 +604,7 @@
                     subject-agr (ref :top)]
                 {:synsem {:cat :verb
                           :essere true
-                          :français {:futuro-stem "ennui"
+                          :français {:future-stem "ennui"
                                      :boot-stem "ennui"}
                           :sem {:pred :get-bored
                                 :reflexive true


added the verb svenire

added the verb svenire

--- src/babel/italiano/lexicon.clj
+++ src/babel/italiano/lexicon.clj
@@ -1609,6 +1609,16 @@
                             :pred :suonare}}}
 ;                                            :obj {:music true}}}})

+ "svenire" {:synsem {:cat :verb
+                      :essere true
+                      :sem {:pred :faint}}
+             :italiano {:passato "svenuto"
+                        :present {:1sing "svengo"
+                                  :2sing "svieni"
+                                  :3sing "sviene"
+                                  :3plur "svengono"}
+                        :futuro-stem "sverr"}}
+
    "svegliarsi" (let [subject-semantics (ref {:animate true})
                       subject-agr (ref :top)]
                   {:synsem {:cat :verb


use dag-unify.core/get-in, not clojure.core/get-in.

--- src/babel/italiano/lexicon.clj
+++ src/babel/italiano/lexicon.clj
@@ -1,8 +1,10 @@
 (ns babel.italiano.lexicon
+  (:refer-clojure :exclude [get-in])
   (:require
    [babel.lexiconfn :refer [compile-lex map-function-on-map-vals unify]]
    [babel.italiano.morphology :as morph]
-   [babel.italiano.pos :refer :all]))
+   [babel.italiano.pos :refer :all]
+   [dag-unify.core :refer [get-in]]))

 (def lexicon-source
   {"Antonia"
@@ -567,7 +569,6 @@
                                 :discrete false
                                 :pred :cercare
                                 :subj {:animate true}}}}
-
       "città"
       (unify agreement-noun
              common-noun
@@ -579,7 +580,6 @@
                              :city true}
                        :subcat {:1 {:cat :det
                                     :def :def}}}})
-
       "cominciare"
       [{:synsem {:essere false
                           :sem {:activity true
@@ -591,7 +591,6 @@
                        :discrete false
                        :pred :start
                        :subj {:animate true}}}}]
-
       "compito"
       (unify agreement-noun
              common-noun
@@ -602,7 +601,6 @@
                              :speakable false
                              :buyable false
                              :artifact true}}})
-

       "commentare"  {:synsem {:cat :verb
                               :sem {:pred :comment}}}


CMR-3694: Added docstring.

CMR-3694: Added docstring.

--- ingest-app/src/cmr/ingest/services/messages.clj
+++ ingest-app/src/cmr/ingest/services/messages.clj
@@ -42,6 +42,7 @@
           (:ShortName project-map) (:LongName project-map)))

 (defn datacenter-not-matches-kms-keywords
+   "Error msg when DataCenter's ShortName, LongName are not in the KMS."
    [datacenter]
    (format "DataCenter short name [%s] and long name [%s] was not a valid keyword combination."
           (:ShortName datacenter) (:LongName datacenter)))


AR|ME Updated flatform>-sg-columns fn

AR|ME Updated flatform>-sg-columns fn

--- src/hatti/views/table.cljs
+++ src/hatti/views/table.cljs
@@ -76,8 +76,7 @@
    "Get a set of slick grid column objects when given a flat form."
   ([form] (flat-form->sg-columns form true))
   ([form get-label?] (flat-form->sg-columns form get-label? nil))
-  ([form get-label? language] (flat-form->sg-columns form get-label? language nil))
-  ([form get-label? language is-filtered-dataview?]
+  ([form get-label? language & {:keys [is-filtered-dataview?]}]
    (clj->js
     (for [field (all-fields form is-filtered-dataview?)]
       (let [{:keys [name type full-name]} field
@@ -97,7 +96,7 @@
   "Creates a Slick.Grid backed by Slick.Data.DataView from data and fields.
    Most events are handled by slickgrid. On double-click, event is put on chan.
    Returns [grid dataview]."
-  (let [columns (flat-form->sg-columns form true nil is-filtered-dataview?)
+  (let [columns (flat-form->sg-columns form true nil :is-filtered-dataview? true)
         SlickGrid (.. js/Slick -Grid)
         DataView (.. js/Slick -Data -DataView)
         Pager (.. js/Slick -Controls -Pager)


Load all sites defined in the resource/sites folder

--- src/clj/comic_reader/sites.clj
+++ src/clj/comic_reader/sites.clj
@@ -209,8 +209,23 @@
 (defn make-site-entry [site-name]
   [site-name (->MangaSite (read-site-options site-name))])

+(defn base-name [file]
+  (let [[_ base-name]
+        (->> file
+             io/as-file
+             .getName
+             (re-matches #"^(.*)\..*?$"))]
+    base-name))
+
+(defn get-all-sites []
+  (->> (io/resource "sites")
+       io/as-file
+       file-seq
+       (filter (complement (memfn isDirectory)))
+       (map base-name)))
+
 (def sites
-  (->> ["manga-fox"]
+  (->> (get-all-sites)
        (map make-site-entry)
        flatten
        (apply hash-map)))


Remove a bunch of dead code

Remove a bunch of dead code

--- src/clj/momentum/http/core.clj
+++ src/clj/momentum/http/core.clj
@@ -2,39 +2,20 @@
   (:use
    momentum.core.buffer)
   (:require
-   [clojure.string     :as str]
-   [momentum.net.message :as msg]
+   [clojure.string       :as str]
    [momentum.http.parser :as parser])
   (:import
    [momentum.core
     Buffer]
-   [org.jboss.netty.buffer
-    ChannelBuffer
-    ChannelBuffers]
-   [org.jboss.netty.handler.codec.http
-    DefaultHttpChunk
-    DefaultHttpRequest
-    DefaultHttpResponse
-    HttpChunk
-    HttpHeaders
-    HttpMessage
-    HttpMethod
-    HttpRequest
-    HttpResponse
-    HttpResponseStatus
-    HttpVersion]
    [java.io
-    IOException]
-   [java.net
-    URI]))
-
-(def SP          (buffer " "))
-(def QM          (buffer "?"))
-(def CRLF        (buffer "\r\n"))
-(def http-1-0    [1 0])
-(def http-1-1    [1 1])
-(def last-chunk  HttpChunk/LAST_CHUNK)
-(def last-chunk* (buffer "0\r\n\r\n"))
+    IOException]))
+
+(def SP         (buffer " "))
+(def QM         (buffer "?"))
+(def CRLF       (buffer "\r\n"))
+(def http-1-0   [1 0])
+(def http-1-1   [1 1])
+(def last-chunk (buffer "0\r\n\r\n"))

 (def response-status-reasons
   {100 "Continue"
@@ -250,161 +231,13 @@
        (dn :message (wrap (buffer size CRLF) chunk CRLF)))

      chunked?
-     (dn :message last-chunk*)
+     (dn :message last-chunk)

      chunk
      (dn :message chunk))))

-;; ==== Most of the code below is deprecated
-
-(defn- netty-assoc-hdrs
-  [^HttpMessage msg hdrs]
-  (doseq [[k v-or-vals] hdrs]
-    (when (string? k)
-      (if (sequential? v-or-vals)
-        (doseq [val v-or-vals]
-          (when-not (empty? val)
-            (.addHeader msg (name k) (str val))))
-        (when-not (or (nil? v-or-vals) (= "" v-or-vals))
-          (.addHeader msg (name k) (str v-or-vals)))))))
-
-(defn- netty-set-content
-  [^HttpMessage msg body]
-  (cond
-   (= :chunked body)
-   (.setChunked msg true)
-
-   body
-   (.setContent msg (to-channel-buffer body))))
-
-(def netty-versions
-  {[1 0] HttpVersion/HTTP_1_0
-   [1 1] HttpVersion/HTTP_1_1})
-
-(defn- headers->uri
-  [{query-string :query-string path-info :path-info}]
-  (if (empty? query-string)
-    path-info
-    (str path-info "?" query-string)))
-
-(defn- ^HttpRequest mk-netty-request
-  [{http-version :http-version request-method :request-method :as headers}]
-  (let [version (netty-versions (or http-version [1 1]))
-        method  (HttpMethod. request-method)
-        uri     (headers->uri headers)]
-    (DefaultHttpRequest. version method uri)))
-
-(defn- ^HttpResponse mk-netty-response
-  [status {http-version :http-version}]
-  (let [version (netty-versions (or http-version [1 1]))
-        status  (HttpResponseStatus/valueOf status)]
-    (DefaultHttpResponse. version status)))
-
-(defn request->netty-request
-  [hdrs body]
-  (doto (mk-netty-request hdrs)
-    (netty-assoc-hdrs hdrs)
-    (netty-set-content body)))
-
-(defn response->netty-response
-  [status hdrs body]
-  (doto (mk-netty-response status hdrs)
-    (netty-assoc-hdrs hdrs)
-    (netty-set-content body)))
-
-(defn chunk->netty-chunk
+(defn chunk-size
   [chunk]
-  (DefaultHttpChunk. (to-channel-buffer chunk)))
-
-(defn- netty-message->version
-  [msg]
-  (let [version (.getProtocolVersion msg)]
-    [(.getMajorVersion version) (.getMinorVersion version)]))
-
-(defn- merge-header
-  [hdrs [k v]]
-  (let [k (str/lower-case k)
-        existing (hdrs k)]
-    (assoc hdrs
-      k (cond
-         (nil? existing)
-         v
-
-         (string? existing)
-         [existing v]
-
-         :else
-         (conj existing v)))))
-
-(defn- netty-message->headers
-  [msg]
-  (-> (reduce merge-header {} (.getHeaders msg))
-      (assoc :http-version (netty-message->version msg))))
-
-(defn- netty-message->body
-  [msg]
-  (cond
-   (.isChunked msg)
-   :chunked
-
-   (.getHeader msg "Content-Length")
-   (.getContent msg)))
-
-(defn- netty-request->headers
-  [request]
-  (let [uri (URI. (.getUri request))]
-    (assoc (netty-message->headers request)
-      :request-method (.. request getMethod toString)
-      :path-info      (.getRawPath uri)
-      :query-string   (or (.getRawQuery uri) "")
-      :script-name    "")))
-
-(defn- netty-response->status
-  [response]
-  (.. response getStatus getCode))
-
-(defn- netty-response->headers
-  [response]
-  (netty-message->headers response))
-
-(defn- netty-response->body
-  [response]
-  (let [status (netty-response->status response)]
-    (when (status-expects-body? status)
-      (netty-message->body response))))
-
-(extend-protocol msg/DecodeMessage
-  HttpRequest
-  (decode [request]
-    (let [headers (netty-request->headers request)
-          body    (netty-message->body request)]
-     [:request  [headers body]]))
-
-  HttpResponse
-  (decode [response]
-    (let [status  (netty-response->status response)
-          headers (netty-response->headers response)
-          body    (netty-response->body response)]
-      [:response [status headers body]]))
-
-  HttpChunk
-  (decode [chunk]
-    [:body (when-not (.isLast chunk) (.getContent chunk))]))
-
-(defprotocol ChunkSize
-  (chunk-size [_]))
-
-(extend-protocol ChunkSize
-  clojure.lang.Keyword
-  (chunk-size [_] 0)
-
-  nil
-  (chunk-size [_] 0)
-
-  Buffer
-  (chunk-size [buf]
-    (remaining buf))
-
-  Object
-  (chunk-size [o]
-    (throw (Exception. (str "Not a valid body chunk type: " o)))))
+  (if (or (nil? chunk) (keyword? chunk))
+    0
+    (remaining chunk)))


Simplify

Simplify

--- src/clj_simple_chart/chart.clj
+++ src/clj_simple_chart/chart.clj
@@ -59,7 +59,6 @@
         (= ::none (get y :axis ::none)) (recur (assoc-in config [:y :axis] :y))
         :else (chart-inner config)))

-(def margin 0)
 (def svg-width 320)
 (def svg-height 240)

@@ -76,15 +75,14 @@
                        "Norway"
                        "United States"]})

-(def cfg {:width  (- svg-width (* 2 margin))
-          :height (- svg-height (* 2 margin))
+(def cfg {:width  svg-width
+          :height svg-height
           :x      xx :y yy})

 (def c (chart cfg))

 (defn diagram []
   [:svg {:xmlns "http://www.w3.org/2000/svg" :width svg-width :height svg-height}
-   [:g {:transform (core/translate margin margin)}

     [:g {:transform (core/translate (:margin-left c) (:margin-top c))}

@@ -101,8 +99,7 @@
      (axis/render-axis (:y c))
      (axis/render-axis (:x c))

-     ]]
-   ])
+     ]])

 (defn render-self []
   (core/render "./img/chart.svg" (diagram)))


resources.cljx edited online with Bitbucket

--- src/cljx/oxylab/resources.cljx
+++ src/cljx/oxylab/resources.cljx
@@ -3,7 +3,7 @@
 (def resources
   {:detrit {:size 0.0
             :max-size 100}
-   :soil {:size 5.0
+   :soil {:size 0.0
           :max-size 100}
    :oxygen {:size 0.0
             :max-size 100}})


simplify main

simplify main

--- src/clojure/confgraph/core.clj
+++ src/clojure/confgraph/core.clj
@@ -26,5 +26,4 @@
   (if (> (count args) 1)
     (do (println "Supply at most a single filtering prefix.")
         (System/exit 1)))
-  (let [fe (edges (first args))]
-    (prn fe)))
+  (prn (edges (first args))))


Rework eval again

Rework eval again

 - Create a module level separation of read forms
 - Create a modules set

The goal with this change is that it paves the way for doing compilation
either on a by module basis or on a whole program basis as it provides
more structure than the simple "seq of forms" AST which really only
enables by form emission of the whole program.

--- src/oxcart.clj
+++ src/oxcart.clj
@@ -94,39 +94,36 @@
          ;;   ana.jvm/analyze invocation is required? I think the
          ;;   answer is no, but it'd be nice.

-         ;; FIXME: Closed over defs
-         ;;   This is gonna be invalid for a whole lot of code. Lambda
-         ;;   lifting is gonna come into play here methinks. I have to
-         ;;   get this working so that closed over defs are supported,
-         ;;   eg:
-         ;;
-         ;;   (let [x 3]
-         ;;     (def foo [y]
-         ;;          (+ x y)))
-         ;;
-         ;; This issue also impacts multimethods which are implemented
-         ;; with closed over defs.
-
-         (do (let [ast (binding [ana/macroexpand-1 ana.jvm/macroexpand-1
-                                 ana/create-var    ana.jvm/create-var
-                                 ana/parse         ana.jvm/parse
-                                 ana/var?          var?]
-                         (ana.jvm/analyze mform
-                                          (or env (ana.jvm/empty-env))))]
-
-               ;; the accumulator for the whole read program
-               (when (and forms
-                          (atom? forms))
-                 (swap! forms conj ast)))
-
-             ;; and run the code for side-effects.
+         (do ;; Run the code for side-effects first
              (let [r     (-> `(^:once fn* [] ~mform)
                              (ana.jvm/analyze (or env (ana.jvm/empty-env)))
                              (e/emit {:debug?       debug?
                                       :class-loader (or classloader
                                                         (clojure.lang.RT/makeClassLoader))}))
                    class (-> r meta :class)]
-               (.invoke ^IFn (.newInstance ^Class class))))))))
+               (.invoke ^IFn (.newInstance ^Class class)))
+
+             ;; Save the AST using (.name *ns*) to determine the module
+             (let [ast (binding [ana/macroexpand-1 ana.jvm/macroexpand-1
+                                 ana/create-var    ana.jvm/create-var
+                                 ana/parse         ana.jvm/parse
+                                 ana/var?          var?]
+                         (ana.jvm/analyze mform
+                                          (or env (ana.jvm/empty-env))))]
+
+               ;; Add to the accumulator for the whole read program
+               ;;
+               ;; Builds a mapping of the form
+               (when (and forms
+                          (atom? forms))
+                 (swap! forms
+                        #(-> %1
+                             (update-in [(.name *ns*) :forms]
+                                        concat [ast])
+                             (update-in [:modules]
+                                        (fn [x]
+                                          (conj (or x #{})
+                                                (.name *ns*)))))))))))))

 (defn load
@@ -162,14 +159,14 @@
            reader (readers/indexing-push-back-reader file 1 p)]
        (binding [*ns*                 *ns*
                  *file*               p
-                 *load-configuration* options
-                 clojure.core/load    oxcart/load
-                 clojure.core/eval    oxcart/eval]
-         (loop []
-           (let [form (r/read reader false eof)]
-             (when (not= eof form)
-               (eval form options)
-               (recur))))))
+                 *load-configuration* options]
+         (with-redefs [clojure.core/load    oxcart/load
+                       clojure.core/eval    oxcart/eval]
+           (loop []
+             (let [form (r/read reader false eof)]
+               (when (not= eof form)
+                 (eval form options)
+                 (recur)))))))
      nil))

@@ -184,18 +181,22 @@
   config-map:
    `:passes` is a sequence of functions constituting an optimization
     configuration. These functions must be
-    (λ form-seq → settings → form-seq)
+    (λ ast → settings → ast)
     and pure. It is expected but not enforced that passes may not
     emit nodes which an emitter does not support. If passes is empty
     no program transformations will be done and the emitter will be
     invoked directly.

-    `:emitter` is a single function which is λ form-seq → nil which
-    is expected to emit the appropriate classfiles as side effects.
+    `:emitter` is a single function which is λ ast → settings → nil
+    which is expected to emit the appropriate classfiles as side
+    effects.

     `:settings` may be a map containing `:passes` and `:emitter`,
     these being option maps which will be applied respectively at the
-    invocation of each pass and the emitter."
+    invocation of each pass and the emitter.
+
+    `[:settings :entry]` is expected to be a fully qualified symbol,
+    being a -main method or other program entry point."

   ([res]
      ;; FIXME:
@@ -216,24 +217,9 @@
        ;; to generate the forms and defs structures.
        (load res config)

-       ;; The atoms now contain the whole analyzed program, apply
-       ;; program passes as updates over the entire AST. Updated ASTs
-       ;; are re-evaluated and the symbol to AST mapping rebuilt
-       ;; between each pass.
-       ;;
-       ;; FIXME: Implementation of method updates
-       ;;   It's worth discussing the correctness of this approach on
-       ;;   the mailing list.
        (let [settings (:passes settings)]
          (doseq [pass passes]
-           (swap! forms pass settings)
-
-           (let [eval-forms @forms]
-             (reset! forms [])
-
-             (doseq [form eval-forms]
-               (eval (:form form)
-                     config)))))
+           (swap! forms pass settings)))

        ;; Having taken an O(Nᵏ) compile operation to the face we now
        ;; run the emitter and call it quits.


Fix typo in documentation of «explore-attributes»

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/exploration.clj
+++ src/conexp/fca/exploration.clj
@@ -37,7 +37,7 @@
     being of the form [g ms], where «g» is a new object and «ms» is
     the set of its attributes.

-  - background-knowledge «set of implications»
+  - :background-knowledge «set of implications»

     background-knowledge denotes a set of implications used as
     background knowledge, which will be subtracted from the computed


xorp: use IGMP v3

xorp: use IGMP v3

--- roles/network/templates/etc/xorp/config.boot
+++ roles/network/templates/etc/xorp/config.boot
@@ -13,6 +13,7 @@
         interface eth0 {
             vif eth0 {
                 disable: false
+                version: 3
             }
         }
         traceoptions {


Get simple list rendering

Get simple list rendering

--- ui/src/bucket/core.cljs
+++ ui/src/bucket/core.cljs
@@ -14,21 +14,21 @@
 (figwheel/start {:websocket-url "ws://localhost:3449/figwheel-ws"})
 (devtools/install!)

-(defonce app (atom {
-  ;; the list of files/folders to display
+(defonce app-state (atom {
+  ;; the list of files to display
   :files []
 }))

-;; FIXME: remove this!
-(add-watch app :debug-watcher
+;; show app state changes for simpler debugging
+(add-watch app-state :debug-watcher
            (fn [_ _ _ _]
-             (.log js/console app)))
+             (.log js/console "State:" app-state)))

 ;; the root element of our application
 (defonce root (.querySelector js/document "main"))

 (GET "/files/"
-     {:handler #(om/update! (om/root-cursor app) :files %)
+     {:handler #(swap! app-state assoc :files %)
       :format :json
       :response-format :json
       :keywords? true
@@ -41,14 +41,15 @@
   ([] (generate-id 16))
   ([length] (apply str (repeatedly length #(rand-nth id-alphabet)))))

-;; a single file or folder
+;; a single file
 (defcomponent file [file owner]
   (render [this]
           (html [:div {:class "file"} (:name file)])))

-(defcomponent file-list [files owner]
+;; a list of files
+(defcomponent file-list [app-state owner]
   (render [this]
           (html [:div {:class "file-list"}
-                 (om/build-all file files)])))
+                 (om/build-all file (:files app-state))])))

-(om/root file-list (:files app) {:target root})
+(om/root file-list app-state {:target root})


Allowing linux plans to be updated with existing stripe customer.

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -395,7 +395,8 @@
              (om/build shared/styled-range-slider
                        (merge app {:start-val selected-containers :min-val min-slider-val :max-val max-slider-val}))]
             [:fieldset
-             (if (and (pm/can-edit-plan? plan org-name) (or (config/enterprise?) (pm/paid? plan)))
+             (if (and (pm/can-edit-plan? plan org-name)
+                      (or (config/enterprise?) (pm/paid? plan) (pm/stripe-customer? plan)))
                (forms/managed-button
                  (let [enterprise-text "Save changes"]
                    (if (and (zero? new-total) (not (config/enterprise?)))


fixed a bug that was crashing chrome

fixed a bug that was crashing chrome

--- src-cljs/tranjlator/core.cljs
+++ src-cljs/tranjlator/core.cljs
@@ -30,11 +30,10 @@
             sender-ch (:sender-ch app)]
         (make-socket listener-ch sender-ch)
         (go (loop []
-              (let [msg (<! listener-ch)
-                    topic (:topic msg)]
+              (when-let [msg (<! listener-ch)]
                 (cond
-                 (= :original topic) (om/transact! app :original (fn [col] (conj col msg)))
-                 (= :user-join topic) (om/transact! app :users (fn [col] (conj col (:user-name msg []))))
+                 (= :original (:topic msg)) (om/transact! app :original (fn [col] (conj col msg)))
+                 (= :user-join (:topic msg)) (om/transact! app :users (fn [col] (conj col (:user-name msg []))))
                  :default (println "RECVD:" msg "type: " (keys msg)))
                 (recur))))))
     om/IRender


Update init function

Update init function

--- src/discuss/communication.cljs
+++ src/discuss/communication.cljs
@@ -75,13 +75,6 @@
         refs (:references res)]
     (lib/update-state-item! :common :references (fn [_] refs))
     (discuss.references.integration/process-references refs)))
-
-(defn init!
-  "Request initial data from API."
-  []
-  (let [url (:init config/api)]
-    (lib/update-state-item! :layout :add? (fn [_] false))
-    (ajax-get-and-change-view url :default)))

 ;;;; Discussion-related functions
@@ -161,4 +154,14 @@
     (= id "item_justify_premise") (prepare-add :add-justify-premise)
     (= url "add") (prepare-add "add")
     (= url "login") (lib/change-view! :login)
-    :else (ajax-get url)))+    :else (ajax-get url)))
+
+
+;;;; Get things started!
+(defn init!
+  "Request initial data from API."
+  []
+  (let [url (:init config/api)]
+    (lib/update-state-item! :layout :add? (fn [_] false))
+    (ajax-get-and-change-view url :default)
+    (request-references)))


Make water and trees non-traversable

Make water and trees non-traversable

--- src/dungeon_crusade/common.clj
+++ src/dungeon_crusade/common.clj
@@ -321,7 +321,9 @@
         (nil? cell)
         (some (fn [collision-type] (= (cell :type) collision-type)) [:vertical-wall
                                                                      :horizontal-wall
-                                                                     :close-door])
+                                                                     :close-door
+                                                                     :water
+                                                                     :tree])
         ;; not a wall or closed door, check for npcs
         (and include-npcs?
              (npc-at-xy state x y)))))))


Reorder functions

Reorder functions

--- src/cljs/cglossa/search_inputs/cwb/shared.cljs
+++ src/cljs/cglossa/search_inputs/cwb/shared.cljs
@@ -7,9 +7,6 @@
   (when (= "Enter" (.-key event))
     (.preventDefault event)
     (search! wrapped-query)))
-
-(defn- on-headword-search-changed [event wrapped-query]
-  (swap! wrapped-query assoc :headword-search (.-target.checked event)))

 (defn remove-row-btn [show? wrapped-query]
   [:button.btn.btn-danger.btn-xs {:type     "button"
@@ -22,8 +19,11 @@
                                                              "hidden")}}
    [:span.glyphicon.glyphicon-remove]])

-(defn- headword-search-checkbox [wrapped-query]
-  [:label {:style {:margin-left 20}}
+(defn- on-headword-search-changed [event wrapped-query]
+  (swap! wrapped-query assoc :headword-search (.-target.checked event)))
+
+(defn headword-search-checkbox [wrapped-query margin-left]
+  [:label {:style {:margin-left margin-left}}
    [:input {:type      "checkbox"
             :value     "1"
             :checked   (:headword-search @wrapped-query)


Show 'Pay now' / 'Update plan' appropriately for piggiebacked plans.

Conflicts:
	src-cljs/frontend/components/org_settings.cljs

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -432,7 +432,7 @@
                     [:i.fa.fa-question-circle#grandfathered-tooltip-hack
                      {:title: "We've changed plan prices since you signed up, so you're grandfathered in at the old price!"}])]]
                 [:fieldset
-                 (if (or (pm/enterprise? plan) (pm/paid? plan))
+                 (if (and (pm/can-edit-plan? plan org-name) (or (pm/enterprise? plan) (pm/paid? plan)))
                    (forms/managed-button
                     [:button.btn.btn-large.btn-primary.center
                      {:data-success-text "Saved",


encapsulate all fn-ality in a fn and begni first stage of integration with DADA

--- dada-swt/src/main/clojure/org/dada/swt/nattable.clj
+++ dada-swt/src/main/clojure/org/dada/swt/nattable.clj
@@ -1,10 +1,12 @@
 (ns
  org.dada.swt.nattable
+ (use org.dada.core)
+ (use org.dada.swt.utils)
  (:import
   [java.util ArrayList]
   [org.eclipse.swt SWT]
   [org.eclipse.swt.layout GridData GridLayout]
-  [org.eclipse.swt.widgets Display Shell]
+  [org.eclipse.swt.widgets Composite Display Shell]
   [ca.odell.glazedlists GlazedLists SortedList]
   [net.sourceforge.nattable NatTable]
   [net.sourceforge.nattable.blink BlinkLayer]
@@ -22,125 +24,109 @@
   [net.sourceforge.nattable.sort SortHeaderLayer]
   [net.sourceforge.nattable.sort.config SingleClickSortConfiguration]
   [net.sourceforge.nattable.viewport ViewportLayer]
+
+  [org.dada.core Metadata Model]
   ))

-
-(def parent (Shell. (Display.)))
-(.setLayout parent (GridLayout.))
-
 ;;--------------------------------------------------------------------------------
-
-;; Basic Table
 ;; see http://nattable.org/drupal/docs/basicgrid
 ;; Sorted Table
 ;; see http://nattable.svn.sourceforge.net/viewvc/nattable/trunk/nattable/net.sourceforge.nattable.examples/src/net/sourceforge/nattable/examples/demo/SortableGridExample.java?revision=3912&view=markup
 ;; Blinking Table
 ;; http://nattable.svn.sourceforge.net/viewvc/nattable/trunk/nattable/net.sourceforge.nattable.examples/src/net/sourceforge/nattable/examples/demo/BlinkingGridExample.java?revision=3912&view=markup

-;;--------------------------------------------------------------------------------
-;; Plugging data
+(defn make-nattable [#^Model model #^Composite parent]
+  (let [#^Metadata metadata (.getMetadata model)
+	attributes (.getAttributes metadata)
+	property-names (into-array String (map (fn [attribute] (.toString (.getKey attribute))) attributes))
+	property-name-to-index (apply array-map (interleave property-names (iterate inc 0)))
+	property-name-to-label (apply array-map (interleave property-names property-names))
+	data (.getExtant (.getData model))
+	event-list (GlazedLists/eventList data)
+	sorted-list (SortedList. event-list nil)
+
+	column-property-accessor
+	(proxy
+	 [IColumnPropertyAccessor]
+	 []
+	 ;; IColumnAccessor<T>
+	 (#^Object getDataValue [#^Collection rowObject #^int columnIndex] (nth rowObject columnIndex))
+	 (#^int getColumnCount [] (count property-names))
+	 ;; public void setDataValue(T rowObject, int columnIndex, Object newValue);
+
+	 ;;IColumnPropertyResolver
+	 (#^String getColumnProperty [int columnIndex] (nth property-names columnIndex))
+	 (#^int getColumnIndex [#^String propertyName] (property-name-to-index propertyName))
+	 )

-(def data (ArrayList. [[3 "alexandra" 2005][1 "jane" 1969][2 "anthony" 2001][0 "jules" 1967]]))
+	config-registry (ConfigRegistry.)
+	body-data-provider (ListDataProvider. sorted-list column-property-accessor)

-(def event-list (GlazedLists/eventList data))
-(def sorted-list (SortedList. event-list nil))
-(def property-names (into-array String ["id" "name" "birthDate"]))
+	body-layer-stack (DefaultBodyLayerStack.
+			   (BlinkLayer.
+			    (GlazedListsEventLayer. (DataLayer. body-data-provider) event-list)
+			    body-data-provider
+			    (proxy [IRowIdAccessor][](#^Serializable getRowId [#^Collection row] (first row)))
+			    column-property-accessor
+			    config-registry))
+
+	column-header-data-provider (DefaultColumnHeaderDataProvider. property-names property-name-to-label)
+	column-header-data-layer (DefaultColumnHeaderDataLayer. column-header-data-provider)
+	column-header-layer (ColumnHeaderLayer. column-header-data-layer body-layer-stack (.getSelectionLayer body-layer-stack))
+	column-header-layer-stack (proxy [AbstractLayerTransform] [])]
+
+    (.setUnderlyingLayer column-header-layer-stack (SortHeaderLayer. column-header-layer (GlazedListsSortModel. sorted-list column-property-accessor config-registry column-header-data-layer) false))
+
+    ;;--------------------------------------------------------------------------------
+    ;; Setting up the row header layer
+
+    (let [row-header-data-provider (DefaultRowHeaderDataProvider. body-data-provider)
+	  row-header-layer (RowHeaderLayer. (DefaultRowHeaderDataLayer. row-header-data-provider) body-layer-stack (.getSelectionLayer body-layer-stack))
+	  row-header-layer-stack (proxy [AbstractLayerTransform] [])]
+      (.setUnderlyingLayer row-header-layer-stack row-header-layer)
+
+      ;; define parent...
+      (doto
+	  (NatTable.
+	   parent
+	   (GridLayer.
+	    body-layer-stack
+	    column-header-layer-stack
+	    row-header-layer
+	    (CornerLayer.
+	     (DataLayer.
+	      (DefaultCornerDataProvider. column-header-data-provider row-header-data-provider))
+	     row-header-layer-stack
+	     column-header-layer-stack))
+	   false)
+	(.setConfigRegistry config-registry)
+	(.addConfiguration (DefaultNatTableStyleConfiguration.))
+	(.addConfiguration (SingleClickSortConfiguration.))
+
+	;;TODO - still to translate
+	;;http://nattable.svn.sourceforge.net/viewvc/nattable/trunk/nattable/net.sourceforge.nattable.examples/src/net/sourceforge/nattable/examples/demo/SortableGridExample.java?revision=3912&view=markup
+	;; nattable.addConfiguration(getCustomComparatorConfiguration(glazedListsGridLayer.getColumnHeaderLayerStack().getDataLayer()));
+	(.addConfiguration (DefaultSelectionStyleConfiguration.))
+	(.configure)
+
+	(.setLayoutData (GridData. (SWT/FILL) (SWT/FILL) true true))
+	(.pack))
+      )))

 ;;--------------------------------------------------------------------------------

-(def property-name-to-index (apply array-map (interleave property-names (iterate inc 0))))
-(def property-name-to-label (apply array-map (interleave property-names property-names)))
+(def table-model (model "Family" (seq-metadata 4)))
+(insert-n table-model (ArrayList. [[3 0 "alexandra" 2005][1 0 "jane" 1969][2 0 "anthony" 2001][0 0 "jules" 1967]]))

-(def column-property-accessor
-     (proxy
-      [IColumnPropertyAccessor]
-      []
-      ;; IColumnAccessor<T>
-      (#^Object getDataValue [#^Collection rowObject #^int columnIndex] (nth rowObject columnIndex))
-      (#^int getColumnCount [] (count property-names))
-      ;; public void setDataValue(T rowObject, int columnIndex, Object newValue);
-
-      ;;IColumnPropertyResolver
-
-      (#^String getColumnProperty [int columnIndex] (nth property-names columnIndex))
-      (#^int getColumnIndex [#^String propertyName] (property-name-to-index "b"))
-      ))
+(if (not *compile-files*)
+  (do
+    (def parent (Shell. (Display.)))
+    (.setLayout parent (GridLayout.))

-(def body-data-provider (ListDataProvider. sorted-list column-property-accessor))
+    (make-nattable table-model parent)

-;;--------------------------------------------------------------------------------
-;; Setting up the body region
-
-(def config-registry (ConfigRegistry.))
-
-(def body-data-layer (DataLayer. body-data-provider))
-
-(def glazed-lists-event-layer (GlazedListsEventLayer. body-data-layer event-list))
-
-(def blink-layer
-     (BlinkLayer.
-      glazed-lists-event-layer
-      body-data-provider
-      (proxy [IRowIdAccessor][](#^Serializable getRowId [#^Collection row] (first row)))
-      column-property-accessor
-      config-registry))
-
-(def body-layer-stack (DefaultBodyLayerStack. blink-layer))
-
-;;--------------------------------------------------------------------------------
-;; Setting up the column header region
-
-(def column-header-data-provider (DefaultColumnHeaderDataProvider. property-names property-name-to-label))
-(def column-header-data-layer (DefaultColumnHeaderDataLayer. column-header-data-provider))
-(def column-header-layer (ColumnHeaderLayer. column-header-data-layer body-layer-stack (.getSelectionLayer body-layer-stack)))
-(def sort-header-layer (SortHeaderLayer. column-header-layer (GlazedListsSortModel. sorted-list column-property-accessor config-registry column-header-data-layer) false))
-(def column-header-layer-stack (proxy [AbstractLayerTransform] []))
-(.setUnderlyingLayer column-header-layer-stack sort-header-layer)
-
-;;--------------------------------------------------------------------------------
-;; Setting up the row header layer
-
-(def row-header-data-provider (DefaultRowHeaderDataProvider. body-data-provider))
-(def row-header-data-layer (DefaultRowHeaderDataLayer. row-header-data-provider))
-(def row-header-layer (RowHeaderLayer. row-header-data-layer body-layer-stack (.getSelectionLayer body-layer-stack)))
-(def row-header-layer-stack (proxy [AbstractLayerTransform] []))
-(.setUnderlyingLayer row-header-layer-stack row-header-layer)
-
-;;--------------------------------------------------------------------------------
-;; Setting up the corner layer
-
-(def corner-data-provider (DefaultCornerDataProvider. column-header-data-provider row-header-data-provider))
-(def corner-data-layer (DataLayer. corner-data-provider))
-(def corner-layer (CornerLayer. corner-data-layer row-header-layer column-header-layer-stack))
-
-;;--------------------------------------------------------------------------------
-;; Drum roll ...
-
-(def grid-layer (GridLayer. body-layer-stack column-header-layer-stack row-header-layer corner-layer))
-;; define parent...
-(def nattable (NatTable. parent grid-layer, false))
-(.setConfigRegistry nattable config-registry)
-(.addConfiguration nattable (DefaultNatTableStyleConfiguration.))
-(.addConfiguration nattable (SingleClickSortConfiguration.))
-
-;;TODO - still to translate
-;;http://nattable.svn.sourceforge.net/viewvc/nattable/trunk/nattable/net.sourceforge.nattable.examples/src/net/sourceforge/nattable/examples/demo/SortableGridExample.java?revision=3912&view=markup
-;; nattable.addConfiguration(getCustomComparatorConfiguration(glazedListsGridLayer.getColumnHeaderLayerStack().getDataLayer()));
-(.addConfiguration nattable (DefaultSelectionStyleConfiguration.))
-(.configure nattable)
-
-(.setLayoutData nattable (GridData. (SWT/FILL) (SWT/FILL) true true))
-(.pack nattable)
-(.pack parent)
-(.open parent)
-
-(defn swt-loop [#^Display display #^Shell shell]
-  (loop []
-    (if (.isDisposed shell)
-      (.dispose display)
-      (do
-	(if (not (.readAndDispatch display))
-	  (.sleep display))
-	(recur)))))
-
-(swt-loop (.getDisplay parent)  parent)
+    (.pack parent)
+    (.open parent)
+    (swt-loop (.getDisplay parent)  parent)
+    ))
+


Update copy for Approval button

Update copy for Approval button

--- src-cljs/frontend/components/pieces/job.cljs
+++ src-cljs/frontend/components/pieces/job.cljs
@@ -101,9 +101,9 @@
                     :disabled? (not= :job-run-status/running status)
                     :on-click #(om-next/transact! this [`(job/approve {:job/id ~id :run/id ~run-id})])}
                    (case status
-                     :job-run-status/succeeded "Workflow Accepted"
-                     :job-run-status/failed "Workflow Rejected"
-                     "Continue Workflow"))])
+                     :job-run-status/succeeded "Approved"
+                     :job-run-status/failed "Declined"
+                     "Approve"))])
                (when (seq required-jobs)
                  [:.requires
                   (requires required-jobs)])]


volume opts form support #217

volume opts form support
#217

--- src/cljs/swarmpit/component/volume/create.cljs
+++ src/cljs/swarmpit/component/volume/create.cljs
@@ -1,18 +1,27 @@
 (ns swarmpit.component.volume.create
   (:require [material.icon :as icon]
             [material.component :as comp]
+            [material.component.list-table-form :as list]
             [material.component.form :as form]
             [material.component.panel :as panel]
             [swarmpit.component.mixin :as mixin]
             [swarmpit.component.state :as state]
             [swarmpit.component.message :as message]
-            [swarmpit.url :refer [dispatch!]]
             [swarmpit.ajax :as ajax]
             [swarmpit.routes :as routes]
             [swarmpit.url :refer [dispatch!]]
+            [sablono.core :refer-macros [html]]
             [rum.core :as rum]))

 (enable-console-print!)
+
+(def form-driver-opts-cursor (conj state/form-value-cursor :options))
+
+(def form-driver-opts-headers
+  [{:name  "Name"
+    :width "35%"}
+   {:name  "Value"
+    :width "35%"}])

 (defn- volume-plugin-handler
   []
@@ -39,7 +48,7 @@

 (defn- form-name [value]
   (form/comp
-    "NAME"
+    "VOLUME NAME"
     (comp/vtext-field
       {:name     "name"
        :key      "name"
@@ -50,7 +59,7 @@

 (defn- form-driver [value plugins]
   (form/comp
-    "DRIVER"
+    "NAME"
     (comp/select-field
       {:value    value
        :onChange (fn [_ _ v]
@@ -61,6 +70,41 @@
                     :value       %
                     :primaryText %}))))))

+(defn- form-driver-opt-name [value index]
+  (list/textfield
+    {:name     (str "form-driver-opt-name-" index)
+     :key      (str "form-driver-opt-name-" index)
+     :value    value
+     :onChange (fn [_ v]
+                 (state/update-item index :name v form-driver-opts-cursor))}))
+
+(defn- form-driver-opt-value [value index]
+  (list/textfield
+    {:name     (str "form-driver-opt-value-" index)
+     :key      (str "form-driver-opt-value-" index)
+     :value    value
+     :onChange (fn [_ v]
+                 (state/update-item index :value v form-driver-opts-cursor))}))
+
+(defn- form-driver-render-opts
+  [item index]
+  (let [{:keys [name value]} item]
+    [(form-driver-opt-name name index)
+     (form-driver-opt-value value index)]))
+
+(defn- form-driver-opts-table
+  [opts]
+  (list/table-raw form-driver-opts-headers
+                  opts
+                  nil
+                  form-driver-render-opts
+                  (fn [index] (state/remove-item index form-driver-opts-cursor))))
+
+(defn- add-driver-opt
+  []
+  (state/add-item {:name  ""
+                   :value ""} form-driver-opts-cursor))
+
 (defn- init-form-state
   []
   (state/set-value {:valid?      false
@@ -70,7 +114,8 @@
 (defn- init-form-value
   []
   (state/set-value {:volumeName nil
-                    :driver     "local"} state/form-value-cursor))
+                    :driver     "local"
+                    :options    []} state/form-value-cursor))

 (def mixin-init-form
   (mixin/init-form
@@ -81,7 +126,7 @@

 (rum/defc form < rum/reactive
                  mixin-init-form [_]
-  (let [{:keys [volumeName driver]} (state/react state/form-value-cursor)
+  (let [{:keys [volumeName driver options]} (state/react state/form-value-cursor)
         {:keys [valid? processing? plugins]} (state/react state/form-state-cursor)]
     [:div
      [:div.form-panel
@@ -94,8 +139,17 @@
           :primary    true
           :onTouchTap create-volume-handler} processing?)]]
      [:div.form-edit
-      (form/form
-        {:onValid   #(state/update-value [:valid?] true state/form-state-cursor)
-         :onInvalid #(state/update-value [:valid?] false state/form-state-cursor)}
-        (form-name volumeName)
-        (form-driver driver plugins))]]))+      [:div.form-layout
+       (form/form
+         {:onValid   #(state/update-value [:valid?] true state/form-state-cursor)
+          :onInvalid #(state/update-value [:valid?] false state/form-state-cursor)}
+         (html
+           [:div.form-layout-group
+            (form-name volumeName)])
+         (html
+           [:div.form-layout-group.form-layout-group-border
+            (form/section "Driver")
+            (form-driver driver plugins)
+            (form/subsection-add "Add volume driver option" add-driver-opt)
+            (when (not (empty? options))
+              (form-driver-opts-table options))]))]]]))


Restructuring

Restructuring

--- src/clojure/clojurewerkz/cassaforte/client.clj
+++ src/clojure/clojurewerkz/cassaforte/client.clj
@@ -29,7 +29,7 @@
             SSLOptions ProtocolOptions$Compression]
            [com.datastax.driver.auth DseAuthProvider]
            [com.google.common.util.concurrent ListenableFuture Futures FutureCallback]
-           java.net.URI
+           [java.net URI]
            [javax.net.ssl TrustManagerFactory KeyManagerFactory SSLContext]
            [java.security KeyStore SecureRandom]
            [com.datastax.driver.core.exceptions DriverException]))
@@ -37,6 +37,38 @@
 (declare build-ssl-options select-compression)

 (def ^:dynamic *fetch-size*)
+(def ^:dynamic *async* false)
+
+;;
+;; Macros
+;;
+
+(defmacro async
+  "Prepare a single statement, return prepared statement"
+  [body]
+  `(binding [*async* true]
+     (do ~body)))
+
+(defmacro with-fetch-size
+  "Temporarily alters fetch size."
+  [^Integer n# & body]
+  `(binding [*fetch-size* ~n#]
+     (do ~@body)))
+
+(defmacro prepare
+  "Prepare a single statement, return prepared statement"
+  ([body]
+     `(binding [hayt/*prepared-statement* true
+                hayt/*param-stack*        (atom [])]
+        ~body))
+  ([session body]
+     `(binding [hayt/*prepared-statement* true
+                hayt/*param-stack*        (atom [])]
+        (.prepare ~session ~body))))
+
+;;
+;; Protocols
+;;

 (defprotocol DummySession
   (executeAsync [_ query]))
@@ -44,6 +76,42 @@
 (deftype DummySessionImpl []
   DummySession
   (executeAsync [_ query] (throw (Exception. "Not connected"))))
+
+(defprotocol BuildStatement
+  (build-statement [query]))
+
+(extend-protocol BuildStatement
+  String
+  (build-statement [query]
+    (build-statement (SimpleStatement. query)))
+
+  clojure.lang.IPersistentMap
+  (build-statement [raw-statement]
+    (build-statement (hayt/->raw raw-statement)))
+
+  Statement
+  (build-statement [s]
+    s))
+
+(defprotocol Listenable
+  (add-listener [_ runnable executor]))
+
+(deftype AsyncResult [fut]
+  clojure.lang.IDeref
+  (deref [_]
+    (conv/to-clj @fut))
+
+  clojure.lang.IBlockingDeref
+  (deref [_ time-period time-unit]
+    (conv/to-clj (deref fut time-period time-unit)))
+
+  Listenable
+  (add-listener [_ runnable executor]
+    (.addListener fut runnable executor)))
+
+;;
+;; Fns
+;;

 (defn ^Cluster build-cluster
   "Builds an instance of Cluster you can connect to.
@@ -186,28 +254,6 @@
   [^Cluster cluster]
   (.close cluster))

-(def ^:dynamic *async* false)
-
-(defmacro async
-  "Prepare a single statement, return prepared statement"
-  [body]
-  `(binding [*async* true]
-     (do ~body)))
-
-(defmacro with-fetch-size
-  "Temporarily alters fetch size."
-  [^Integer n# & body]
-  `(binding [*fetch-size* ~n#]
-     (do ~@body)))
-
-(defn- set-statement-options-
-  [^Statement statement]
-  (when cp/*retry-policy*
-    (.setRetryPolicy statement cp/*retry-policy*))
-  (when cp/*consistency-level*
-    (.setConsistencyLevel statement (cp/resolve-consistency-level cp/*consistency-level*)))
-  statement)
-
 (defn ^:private build-statement-
   "Builds a Prepare or Simple statement out of given params.

@@ -221,62 +267,43 @@
      (set-statement-options- (SimpleStatement. string-query))))

 (defn bind
+  "Binds prepared statement to values, for example:
+
+   With string statement:
+
+      (client/bind
+             (client/prepare s \"INSERT INTO users (name, city, age) VALUES (?, ?, ?);\")
+             [\"Alex\" \"Munich\" (int 19)])
+
+    With queries:
+
+      (let [prepared (client/prepare (insert s :users {:name ? :city ? :age  ?}))]
+        (client/execute s
+                (client/bind prepared [\"Alex\" \"Munich\" (int 19)]))"
   [^PreparedStatement statement values]
   (.bind statement (to-array values)))

-(defmacro prepare
-  "Prepare a single statement, return prepared statement"
-  ([body]
-     `(binding [hayt/*prepared-statement* true
-                hayt/*param-stack*        (atom [])]
-        ~body))
-  ([session body]
-     `(binding [hayt/*prepared-statement* true
-                hayt/*param-stack*        (atom [])]
-        (.prepare ~session ~body))))
-
-(defprotocol BuildStatement
-  (build-statement [query]))
-
-(extend-protocol BuildStatement
-  String
-  (build-statement [query]
-    (build-statement (SimpleStatement. query)))
-
-  clojure.lang.IPersistentMap
-  (build-statement [raw-statement]
-    (build-statement (hayt/->raw raw-statement)))
-
-  Statement
-  (build-statement [s]
-    s))
-
-(defprotocol Listenable
-  (add-listener [_ runnable executor]))
-
-(deftype AsyncResult [fut]
-  clojure.lang.IDeref
-  (deref [_]
-    (conv/to-clj @fut))
-
-  clojure.lang.IBlockingDeref
-  (deref [_ time-period time-unit]
-    (conv/to-clj (deref fut time-period time-unit)))
-
-  Listenable
-  (add-listener [_ runnable executor]
-    (.addListener fut runnable executor)))
-
 (defn execute
-  [^Session session query]
-  (if hayt/*prepared-statement*
-    (let [^String q (hayt/->raw query)]
-      (.prepare session q))
-    (let [^Statement built-statement (build-statement query)]
-      (if *async*
-        (AsyncResult. (.executeAsync session built-statement))
-        (-> (.execute session built-statement)
-            (conv/to-clj))))))
+  "Executes a statement"
+  ([^Session session query]
+     (if hayt/*prepared-statement*
+       (let [^String q (hayt/->raw query)]
+         (.prepare session q))
+       (let [^Statement built-statement (build-statement query)]
+         (if *async*
+           (AsyncResult. (.executeAsync session built-statement))
+           (-> (.execute session built-statement)
+               (conv/to-clj))))))
+  ([^Session session query & {:keys [retry-policy consistency-level]}]
+     (let [^Statement built-statement (build-statement query)]
+       (when retry-policy
+         (.setRetryPolicy built-statement retry-policy))
+       (when consistency-level
+         (.setConsistencyLevel built-statement consistency-level*))
+       (if *async*
+         (AsyncResult. (.executeAsync session built-statement))
+         (-> (.execute session built-statement)
+             (conv/to-clj))))))

 (defn ^String export-schema
   "Exports the schema as a string"


use cannonical path in load-sample*

use cannonical path in load-sample*

--- src/overtone/sc/sample.clj
+++ src/overtone/sc/sample.clj
@@ -36,7 +36,8 @@
 (defn- load-sample*
   [path & args]
   (let [path (resolve-tilde-path path)
-        f    (file path)]
+        f    (file path)
+        path (.getCanonicalPath f)]
     (when-not (.exists f)
       (throw (Exception. (str "Unable to load sample - file does not exist: " path))))
     (let [f-name (.getName f)


pull in in-unested-osc-bundle

pull in in-unested-osc-bundle

--- src/overtone/sc/server.clj
+++ src/overtone/sc/server.clj
@@ -9,7 +9,7 @@
         [overtone.sc.machinery allocator]
         [overtone.sc.machinery.server connection comms]
         [overtone.helpers.lib :only [deref!]]
-        [overtone.osc :only [in-osc-bundle without-osc-bundle]])
+        [overtone.osc :only [in-osc-bundle without-osc-bundle in-unested-osc-bundle]])
   (:require [overtone.config.log :as log]))

 (defn connection-info


Update clientbound

Update clientbound

--- src/packet_definitions.clj
+++ src/packet_definitions.clj
@@ -275,7 +275,7 @@
    :id 0
    :fields [{:name "entity_id" :type "i32" :getter "Get the ID of the created object" :read "varint"}
             {:name "object_uuid" :type "u128" :getter "Get the UUID of the created object"}
-            {:name "object_type" :type "u8"}
+            {:name "object_type" :type "i32" :read "varint"}
             {:name "x" :type "f64" :getter "Get the X coordinate"}
             {:name "y" :type "f64" :getter "Get the Y coordinate"}
             {:name "z" :type "f64" :getter "Get the Z coordinate"}
@@ -312,8 +312,7 @@
             {:name "head_pitch" :type "i8" :getter "Get the pitch of the head of the mob"}
             {:name "velocity_x" :type "i16" :getter "Get the X velocity"}
             {:name "velocity_y" :type "i16" :getter "Get the Y velocity"}
-            {:name "velocity_z" :type "i16" :getter "Get the Z velocity"}
-            {:name "metadata" :type "Vec<u8>" :getter "Get the raw metadata field. This library does not currently attempt to parse this field" :read "bytearray_to_end"}]}
+            {:name "velocity_z" :type "i16" :getter "Get the Z velocity"}]}
   {:name "SpawnPainting"
    :id 4
    :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID of the painting" :read "varint"}
@@ -329,8 +328,7 @@
             {:name "y" :type "f64" :getter "Get the Y coordinate"}
             {:name "z" :type "f64" :getter "Get the Z coordinate"}
             {:name "yaw" :type "i8" :getter "Get the yaw"}
-            {:name "pitch" :type "i8" :getter "Get the pitch"}
-            {:name "metadata" :type "Vec<u8>" :getter "Get the raw metadata in the packet, this library does not attempt to parse this field" :read "bytearray_to_end"}]}
+            {:name "pitch" :type "i8" :getter "Get the pitch"}]}
   {:name "ClientboundAnimation"
    :id 6
    :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID doing the animation" :read "varint"}
@@ -339,69 +337,68 @@
    :id 7
    :automatic-serialize false
    :fields  [{:name "values" :type "BTreeMap<String, i32>" :getter "Get the statistics, with the key being the name of the statistic and the value being the value."}]}
+  {:name "AcknowledgePlayerDigging"
+   :id 8
+   :fields [{:name "location" :type "(i32, i32, i32)" :getter "Gets the position where the digging was happening" :read "position"}
+            {:name "block" :type "i32" :getter "Get the block ID" :read "varint"}
+            {:name "status" :type "i32" :getter "Get the status as a raw VarInt enum" :read "varint"}
+            {:name "successful" :type "bool" :getter "True if the digging succeeded; false if the client should undo any changes it made locally."}]}
   {:name "BlockBreakAnimation"
-   :id 8
+   :id 9
    :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID doing the animation" :read "varint"}
             {:name "location" :type "(i32, i32, i32)" :read "position" :getter "Get the block position"}
 	    {:name "destroy_stage" :type "u8" :getter "Get the destroy stage"}]}
   {:name "UpdateBlockEntity"
-   :id 9
+   :id 10
    :fields [{:name "position" :type "(i32, i32, i32)" :getter "Get the (x, y, z) position" :read "position"}
             {:name "action" :type "u8" :getter "Get the action ID being performed"}
             {:name "nbt" :type "Vec<u8>" :getter "Get the raw NBT bytes" :read "bytearray_to_end"}]}
   {:name "BlockAction"
-   :id 10
+   :id 11
    :fields [{:name "position" :type "(i32, i32, i32)" :getter "Get the (x, y, z) position" :read "position"}
             {:name "action_id" :type "u8" :getter "Get the action ID"}
             {:name "action_param" :type "u8" :getter "Get the action parameter"}
             {:name "block_type" :type "i32" :getter "Get the block type" :read "varint"}]}
   {:name "BlockChange"
-   :id 11
+   :id 12
    :fields [{:name "position" :type "(i32, i32, i32)" :getter "Get the (x, y, z) position" :read "position"}
             {:name "new_block" :type "i32" :getter "Get the new block state ID for the block" :read "varint"}]}
   {:name "BossBar"
-   :id 12
+   :id 13
    :fields [{:name "data" :type "Vec<u8>" :getter "Get the raw data from this packet. Parsing this is very dependent on the specific client, and doing so would be out of scope for this library, therefore parsing this packet is left to the user of the library." :read "bytearray_to_end"}]}
   {:name "ServerDifficulty"
-   :id 13
-   :fields [{:name "difficulty" :type "u8" :getter "Get the difficulty"}]}
+   :id 14
+   :fields [{:name "difficulty" :type "u8" :getter "Get the difficulty"}
+            {:name "difficulty_locked" :type "bool" :getter "Get whether or not the difficulty is locked"}]}
   {:name "ChatMessage"
-   :id 14
+   :id 15
    :fields [{:name "chat" :type "String" :getter "Get the raw JSON data of the chat message. See also ozelot::utils::chat_to_str"}
             {:name "position" :type "u8" :getter "Get the position of the chat message (enum)"}]}
   {:name "MultiBlockChange"
-   :id 15
+   :id 16
    :automatic-serialize false
    :fields [{:name "chunk_x" :type "i32" :getter "Get the chunk X coordinate"}
             {:name "chunk_z" :type "i32" :getter "Get the chunk Z coordinate"}
             {:name "changes" :type "Vec<(u8, u8, u8, i32)>" :getter "Get the changes as a vector, in the form of Vec<(x, y, z, new_block_state)>, where the x, y, z are relative to the chunk."}]}
 {:name "ClientboundTabComplete"
- :id 16
+ :id 17
  :automatic-serialize false
  :fields [{:name "transaction_id" :type "i32" :getter "Get the transaction ID"}
           {:name "start" :type "i32" :getter "Get the start position of the text to replace"}
           {:name "length" :type "i32" :getter "Get the length of the text to replace"}
 	  {:name "matches" :type "Vec<(String, Option<String>)>" :getter "Get the eligible values to insert, with a corresponding tooltip if available."}]}
 {:name "DeclareCommands"
- :id 17
+ :id 18
  ; It might make sense for ozelot to parse this command, I just haven't gotten around to understanding the Node format
  :fields [{:name "raw_data" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the raw packet data"}]}
 {:name "ClientboundConfirmTransaction"
- :id 18
+ :id 19
  :fields [{:name "window_id" :type "u8" :getter "Get the window ID"}
           {:name "action_id" :type "i16" :getter "Get the action ID (nonce)"}
           {:name "accepted" :type "bool"}]}
 {:name "ClientboundCloseWindow"
- :id 19
+ :id 20
  :fields [{:name "window_id" :type "u8" :getter "Get the window ID"}]}
-{:name "OpenWindow"
- :id 20
- :automatic-serialize false
- :fields [{:name "window_id" :type "u8" :getter "Get the window ID"}
-          {:name "window_type" :type "String" :getter "Get the window type"}
-          {:name "window_title" :type "String" :getter "Get the raw JSON of the window title"}
-          {:name "number_of_slots" :type "u8" :getter "Get the number of slots in the window"}
-          {:name "entity_id" :type "Option<i32>" :getter "Get the entity ID if the window type is `EntityHorse`, else `None`"}]}
 {:name "WindowItems"
  :id 21
  :fields [{:name "window_id" :type "u8" :getter "Get the window ID"}
@@ -440,12 +437,8 @@
  :id 28
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID"}
           {:name "status" :type "u8" :getter "Get the status of the entity"}]}
-{:name "NBTQueryResponse"
+{:name "Explosion"
  :id 29
- :fields [{:name "transaction_id" :type "i32" :read "varint" :getter "Get the transaction ID"}
-          {:name "nbt" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the raw NBT data"}]}
-{:name "Explosion"
- :id 30
  :automatic-serialize false
  :fields [{:name "x" :type "f32" :getter "Get the X coordinate"}
           {:name "y" :type "f32" :getter "Get the Y coordinate"}
@@ -456,13 +449,18 @@
           {:name "motion_y" :type "f32" :getter "Get the motion in the Y direction that the player suffers as a result of the explosion"}
           {:name "motion_z" :type "f32" :getter "Get the motion in the Z direction that the player suffers as a result of the explosion"}]}
 {:name "UnloadChunk"
- :id 31
+ :id 30
  :fields [{:name "chunk_x" :type "i32" :getter "Get the chunk's X coordinate"}
           {:name "chunk_z" :type "i32" :getter "Get the chunk's Z coordinate"}]}
 {:name "ChangeGameState"
- :id 32
+ :id 31
  :fields [{:name "action" :type "u8" :getter "Get the reason for the change as a byte"}
           {:name "value" :type "f32" :getter "Get the value, its meaning depends on the action"}]}
+{:name "OpenHorseWindow"
+ :id 32
+ :fields [{:name "window_id" :type "u8" :getter "Get the window id"}
+          {:name "number_of_slots" :type "i32" :getter "Get the amount of slots"}
+          {:name "entity_id" :type "i32" :getter "Get the entity ID"}]}
 {:name "KeepAlive"
  :id 33
  :fields [{:name "id" :type "i64" :getter "Get the ID of the keep alive packet"}]}
@@ -480,39 +478,50 @@
  :automatic-serialize false
  :fields [{:name "particle_id" :type "i32" :getter "Get the particle ID"}
           {:name "use_long_distance" :type "bool" :getter "Get whether to use long distance (65536) instead of short (256)"}
-          {:name "x" :type "f32" :getter "Get the X coordinate"}
-          {:name "y" :type "f32" :getter "Get the Y coordinate"}
-          {:name "z" :type "f32" :getter "Get the Z coordinate"}
+          {:name "x" :type "f64" :getter "Get the X coordinate"}
+          {:name "y" :type "f64" :getter "Get the Y coordinate"}
+          {:name "z" :type "f64" :getter "Get the Z coordinate"}
           {:name "offset_x" :type "f32" :getter "Get the X offset"}
           {:name "offset_y" :type "f32" :getter "Get the Y offset"}
           {:name "offset_z" :type "f32" :getter "Get the Z offset"}
           {:name "particle_data" :type "f32" :getter "Get the particle data for each particle"}
           {:name "count" :type "i32" :getter "Get the amount of particles to create"}
           {:name "data" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the particle data"}]}
+{:name "UpdateLight"
+ :id 37
+ :fields [{:name "chunk_x" :type "i32" :getter "Chunk X coordinate" :read "varint"}
+          {:name "chunk_z" :type "i32" :getter "Chunk Z coordinate" :read "varint"}
+          {:name "sky_light_mask" :type "i32" :getter "Get the sky light mask" :read "varint"}
+          {:name "block_light_mask" :type "i32" :getter "Get the block light mask" :read "varint"}
+          {:name "empty_sky_light_mask" :type "i32" :getter "Get the empty sky light mask" :read "varint"}
+          {:name "empty_block_light_mask" :type "i33" :getter "Get the empty block light mask" :read "varint"}
+          {:name "data" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the light data"}]}
 {:name "JoinGame"
- :id 37
+ :id 38
  :fields [{:name "entity_id" :type "i32" :getter "Get the player's entity ID"}
           {:name "gamemode" :type "u8" :getter "Get the player's gamemode"}
           {:name "dimension" :type "i32" :getter "Get the dimension the player is in. Not the specific world (in case of servers with multiworld), but the kind of world"}
-          {:name "difficulty" :type "u8" :getter "Get the difficulty"}
+          {:name "hashed_seed" :type "i64" :getter "Get the first 8 bytes of the SHA-256 hash of the world's seed"}
           {:name "max_players" :type "u8"}; Apparently this field is no longer used but for some reason hasn't been removed yet
           {:name "level_type" :type "String" :getter "Get the level type of the world the player joined in"}
-          {:name "reduced_debug" :type "bool" :getter "Get whether to show reduced debug info"}]}
+          {:name "view_distance" :type "i32" :getter "Get the render distance in chunks" :read "varint"}
+          {:name "reduced_debug" :type "bool" :getter "Get whether to show reduced debug info"}
+          {:name "enable_respawn_screen" :type "bool" :getter "Get whether or not the respawn screen should be shown. Will be false if the doImmediateRespawn gamerule is true."}]}
 {:name "Map"
- :id 38
+ :id 39
  :fields [{:name "data" :type "Vec<u8>" :getter "Get the raw data from this packet. Parsing this is very dependent on the specific client, and doing so would be out of scope for this library, therefore parsing this packet is left to the user of the library." :read "bytearray_to_end"}]}
-{:name "Entity"
- :id 39
- :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}]}
+{:name "TradeList"
+ :id 40
+ :fields [{:name "data" :type "Vec<u8>" :getter "Get the raw data from this packet. Parsing this is very dependent on the specific client, and doing so would be out of scope for this library, therefore parsing this packet is left to the user of the library." :read "bytearray_to_end"}]}
 {:name "EntityRelativeMove"
- :id 40
+ :id 41
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "x" :type "i16" :getter "Get the relative distance moved in the X direction times 128"}
           {:name "y" :type "i16" :getter "Get the relative distance moved in the Y direction times 128"}
           {:name "z" :type "i16" :getter "Get the relative distance moved in the Z direction times 128"}
           {:name "on_ground" :type "bool" :getter "Get whether the entity is on the ground"}]}
 {:name "EntityLookRelativeMove"
- :id 41
+ :id 42
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "x" :type "i16" :getter "Get the relative distance moved in the X direction times 128"}
           {:name "y" :type "i16" :getter "Get the relative distance moved in the Y direction times 128"}
@@ -521,44 +530,55 @@
           {:name "pitch" :type "i8" :getter "Get the pitch"}
           {:name "on_ground" :type "bool" :getter "Get whether the entity is on the grouns"}]}
 {:name "EntityLook"
- :id 42
+ :id 43
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "yaw" :type "i8" :getter "Get the (absolute) angle"}
           {:name "pitch" :type "i8" :getter "Get the (absolute) pitch"}
           {:name "on_ground" :type "bool" :getter "Get whether on the ground"}]}
+{:name "Entity"
+ :id 44
+ :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}]}
 {:name "ClientboundVehicleMove"
- :id 43
+ :id 45
  :fields [{:name "x" :type "f64" :getter "Get the X coordinate"}
           {:name "y" :type "f64" :getter "Get the Y coordinate"}
           {:name "z" :type "f64" :getter "Get the Z coordinate"}
           {:name "yaw" :type "i8" :getter "Get the (absolute) angle"}
           {:name "pitch" :type "i8" :getter "Get the (absolute) pitch"}]}
+{:name "OpenBook"
+ :id 46
+ :fields [{:name "hand" :type "i32" :getter "Get the hand containing the book to open as a raw varint enum" :read "varint"}]}
+{:name "OpenWindow"
+ :id 47
+ :fields [{:name "window_id" :type "i32" :getter "Get the window ID" :read "varint"}
+          {:name "window_type" :type "i32" :getter "Get the window type" :read "varint"}
+          {:name "window_title" :type "String" :getter "Get the raw JSON of the window title"}]}
 {:name "OpenSignEditor"
- :id 44
+ :id 48
  :fields [{:name "position" :type "(i32, i32, i32)" :getter "Get the (x, y, z) position" :read "position"}]}
 {:name "CraftRecipeResponse"
- :id 45
+ :id 49
  :fields [{:name "window_id" :type "u8" :getter "Get the window ID"}
           {:name "recipe" :type "i32" :getter "Get the recipe ID" :read "varint"}
           ]
  }
 {:name "PlayerAbilities"
- :id 46
+ :id 50
  :fields [{:name "flags" :type "u8"}
           {:name "flying_speed" :type "f32" :getter "Get the player's allowed flying speed"}
           {:name "fov" :type "f32" :getter "Get the player's field of view modifier"}]}
 {:name "CombatEvent"
- :id 47
+ :id 51
  :automatic-serialize false
  :fields [{:name "event" :type "i32"}
           {:name "duration_playerid" :type "Option<i32>" :getter "Get the duration or player ID, depending on type of event"}
           {:name "entity_id" :type "Option<i32>" :getter "Get the entity ID if packet action is 'end combat' or 'entity dead'"}
           {:name "message" :type "Option<String>"}]}
 {:name "PlayerListItem"
- :id 48
+ :id 52
  :fields [{:name "data" :type "Vec<u8>" :getter "Get the raw data from this packet. This library does not attempt to parse this packet." :read "bytearray_to_end"}]}
 {:name "FacePlayer"
- :id 49
+ :id 53
  :automatic-serialize false
  :fields [{:name "feet_or_eyes" :type "i32" :getter "Get whether feet or eyes (enum)"}
           {:name "x" :type "f64" :getter "Get the X coordinate of the point to face"}
@@ -567,7 +587,7 @@
 	  {:name "entity_id" :type "Option<i32>" :getter "Get the entity ID to face toward, if any"}
 	  {:name "entity_feet_or_eyes" :type "Option<i32>" :getter "Get whether to look at the entities eyes or feet (if any entity)"}]}
 {:name "PlayerPositionAndLook"
- :id 50
+ :id 54
  :fields [{:name "x" :type "f64" :getter "Get the x coordinate"}
           {:name "y" :type "f64" :getter "Get the y coordinate"}
           {:name "z" :type "f64" :getter "Get the z coordinate"}
@@ -575,12 +595,8 @@
           {:name "pitch" :type "f32" :getter "Get the pitch"}
           {:name "flags" :type "u8" :getter "Get the raw flags bitmask"}
           {:name "teleport_id" :type "i32" :getter "Get the teleport ID to be used in the serverbound TeleportConfirm packet." :read "varint"}]}
-{:name "UseBed"
- :id 51
- :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID of the player sleeping" :read "varint"}
-          {:name "position" :type "(i32, i32, i32)" :getter "Get the (x, y, z) position" :read "position"}]}
 {:name "UnlockRecipes"
- :id 52
+ :id 55
  :automatic-serialize false
  :fields [{:name "action" :type "i32" :getter "Get the action enum ID"}
           {:name "crafting_book_open" :type "bool" :getter "Get whether the crafting book shall open when the player opens their inventory"}
@@ -590,114 +606,122 @@
 	  {:name "recipes" :type "Vec<String>" :getter "Get all the recipes in list 1"}
 	  {:name "recipes2" :type "Vec<String>" :getter "Get all the recipes in list 2. Is empty unless action == 0"}]}
 {:name "DestroyEntities"
- :id 53
+ :id 56
  :fields [{:name "entity_ids" :type "Vec<i32>" :getter "Get the list of entity IDs that have been destroyed" :read "prefixed_varintarray"}]}
 {:name "RemoveEntityEffect"
- :id 54
+ :id 57
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID to remove the effect from" :read "varint"}
           {:name "effect_id" :type "u8" :getter "Get the effect ID (enum)"}]}
 {:name "ResourcePackSend"
- :id 55
+ :id 58
  :fields [{:name "url" :type "String" :getter "Get the URL to the resource pack"}
           {:name "hash" :type "String" :getter "Get the expected SHA-1 hash of the resource pack"}]}
 {:name "Respawn"
- :id 56
+ :id 59
  :fields  [{:name "dimension" :type "i32" :getter "Get the integer value for the dimension the player is spawning in"}
-           {:name "difficulty" :type "u8" :getter "Get the integer value for the difficulty"}
+           {:name "hashed_seed" :type "i64" :getter "Get the first 8 bytes of the SHA-256 hash of the world's seed"}
            {:name "gamemode" :type "u8" :getter "Get the integer value for the gamemode"}
            {:name "level_type" :type "String" :getter "Get the level type"}]}
 {:name "EntityHeadLook"
- :id 57
+ :id 60
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "head_yaw" :type "i8" :getter "Get the new head yaw"}]}
 {:name "SelectAdvancementTab"
- :id 58
+ :id 61
  :automatic-serialize false
  :fields [{:name "identifier" :type "Option<String>" :getter "Get the identifier to switch to. If None, switch to default"}]}
 {:name "WorldBorder"
- :id 59
+ :id 62
  :fields [{:name "data" :type "Vec<u8>" :getter "Get this packet's raw data. This library does not attempt to parse this packet" :read "bytearray_to_end"}]}
 {:name "Camera"
- :id 60
+ :id 63
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID to set the camera to" :read "varint"}]}
 {:name "ClientboundHeldItemChange"
- :id 61
+ :id 64
  :fields [{:name "slot" :type "u8" :getter "Get the slot number which the player has selected"}]}
+{:name "UpdateViewPosition"
+ :id 65
+ :fields [{:name "chunk_x" :type "i32" :getter "Gets the chunk X coordinate" :read "varint"}
+          {:name "chunk_z" :type "i32" :getter "Gets the chunk Z coordinate" :read "varint"}]}
+{:name "UpdateViewDistance"
+ :id 66
+ :fields [{:name "view_distance" :type "i32" :getter "Gets the render distance, in chunks" :read "varint"}]}
 {:name "DisplayScoreboard"
- :id 62
+ :id 67
  :fields [{:name "position" :type "u8" :getter "Get the raw integer representing the scoreboard's position"}
           {:name "name" :type "String" :getter "Get the name of the scoreboard"}]}
 {:name "EntityMetadata"
- :id 63
+ :id 68
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID of the entity which metadata is being updated" :read "varint"}
           {:name "metadata" :type "Vec<u8>" :getter "Get the raw data for the metadata. This library does not attempt to parse the metadata." :read "bytearray_to_end"}]}
 {:name "AttachEntity"
- :id 64
+ :id 69
  :fields [{:name "attached_entity_id" :type "i32" :getter "Get the entity ID of the entity that has been attached"}
           {:name "holding_entity_id" :type "i32" :getter "Get the entity ID of the entity that has been attached to"}]}
 {:name "EntityVelocity"
- :id 65
+ :id 70
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "x_velocity" :type "i16" :getter "Get the X velocity"}
           {:name "y_velocity" :type "i16" :getter "Get the Y velocity"}
           {:name "z_velocity" :type "i16" :getter "Get the Z velocity"}]}
 {:name "EntityEquipment"
- :id 66
+ :id 71
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "slot_enum" :type "i32" :getter "Get the raw slot identification number" :read "varint"}
           {:name "slot_data" :type "Vec<u8>" :getter "Get the raw slot data. This library does not attempt to parse it" :read "bytearray_to_end"}]}
 {:name "SetExperience"
- :id 67
+ :id 72
  :fields [{:name "experience" :type "f32" :getter "Get how filled up the experience bar is"}
           {:name "level" :type "i32" :getter "Get the new level" :read "varint"}
           {:name "total_experience" :type "i32" :getter "Get the total experience" :read "varint"}]}
 {:name "UpdateHealth"
- :id 68
+ :id 73
  :fields [{:name "health" :type "f32" :getter "Get how much health the player has"}
           {:name "food" :type "i32" :getter "Get how much food the player has" :read "varint"}
           {:name "saturation" :type "f32" :getter "Get the saturation level"}]}
 {:name "ScoreboardObjective"
- :id 69
+ :id 74
  :automatic-serialize false
  :fields [{:name "name" :type "String" :getter "Get the name for the object"}
           {:name "mode" :type "u8" :getter "Get the raw mode enum integer"}
           {:name "value" :type "Option<String>" :getter "Get the text to be displayed"}
           {:name "objective_type" :type "Option<String>" :getter "Get the raw string representing the type (`integer` or `hearts`)"}]}
 {:name "SetPassengers"
- :id 70
+ :id 75
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "passengers" :type "Vec<i32>" :getter "Get the vec of all the passengers" :read "prefixed_varintarray"}]}
 {:name "Teams"
- :id 71
+ :id 76
  :fields [{:name "data" :type "Vec<u8>" :getter "Get the raw data, this library does not attempt to parse this packet." :read "bytearray_to_end"}]}
 {:name "UpdateScore"
- :id 72
+ :id 77
  :automatic-serialize false
  :fields [{:name "name" :type "String" :getter "Get the name of the score to be updated"}
           {:name "action" :type "u8" :getter "Get the action being performed"}
           {:name "objective_name" :type "String" :getter "Get the name of the objective the score belongs to"}
           {:name "value" :type "Option<i32>" :getter "Get the score to be displayed if this packet is updating a score, else `None`"}]}
 {:name "SpawnPosition"
- :id 73
+ :id 78
  :fields [{:name "position" :type "(i32, i32, i32)" :getter "Get the position" :read "position"}]}
 {:name "TimeUpdate"
- :id 74
+ :id 79
  :fields [{:name "world_age" :type "i64" :getter "Get the world's age in ticks"}
           {:name "time_of_day" :type "i64" :getter "Get the current time in ticks (0 is sunrise, 6000 is noon, ...)"}]}
 {:name "Title"
- :id 75
+ :id 80
  :automatic-serialize false
  :fields [{:name "action" :type "i32" :getter "Get the raw action enum integer"}
           {:name "text" :type "Option<String>" :getter "Get the title/subtitle/action bar text if action is set title/subtitle/action bar in raw json"}
           {:name "times" :type "Option<(i32, i32, i32)>" :getter "If action is 'set times and display' get `Some((fade_in, stay, fade_out))` else get `None`"}]}
-{:name "StopSound"
- :id 76
- :automatic-serialize false
- :fields [{:name "flags" :type "u8"}
-          {:name "source" :type "Option<i32>" :getter "Get the source to stop sound from. If None stop from all sources."}
-	  {:name "sound" :type "Option<String>" :getter "Get the identifier to stop, if relevant."}]}
+{:name "EntitySoundEffect"
+ :id 81
+ :fields [{:name "sound_id" :type "i32" :getter "Gets the sound ID" :read "varint"}
+          {:name "sound_category" :type "i32" :getter "Gets the sound category" :read "varint"}
+          {:name "entity_id" :type "i32" :getter "Gets the entity UUID" :read "varint"}
+          {:name "volume" :type "f32" :getter "Gets the sound volume"}
+          {:name "pitch" :type "f32" :getter "Gets the sound pitch"}]}
 {:name "SoundEffect"
- :id 77
+ :id 82
  :fields [{:name "sound_id" :type "i32" :getter "Get the raw sound effect ID. Note that the meaning of this is liable to change between MC releases." :read "varint"}
           {:name "sound_category" :type "i32" :getter "Get the raw sound category ID." :read "varint"}
           {:name "x" :type "i32" :getter "Get the X effect multiplied by 8"}
@@ -705,17 +729,27 @@
           {:name "z" :type "i32" :getter "Get the Z effect multiplied by 8"}
           {:name "volume" :type "f32" :getter "Get the volume where 1.0 is 100%"}
           {:name "pitch" :type "f32" :getter "Get the pitch"}]}
+{:name "StopSound"
+ :id 83
+ :automatic-serialize false
+ :fields [{:name "flags" :type "u8"}
+          {:name "source" :type "Option<i32>" :getter "Get the source to stop sound from. If None stop from all sources."}
+	  {:name "sound" :type "Option<String>" :getter "Get the identifier to stop, if relevant."}]}
 {:name "PlayerListHeaderFooter"
- :id 78
+ :id 84
  :fields [{:name "header" :type "String" :getter "Get the raw json data for the header"}
           {:name "footer" :type "String" :getter "Get the raw json data for the footer"}]}
+{:name "NBTQueryResponse"
+ :id 85
+ :fields [{:name "transaction_id" :type "i32" :read "varint" :getter "Get the transaction ID"}
+          {:name "nbt" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the raw NBT data"}]}
 {:name "CollectItem"
- :id 79
+ :id 86
  :fields [{:name "collected_entity_id" :type "i32" :getter "Get the entity ID of the collected item" :read "varint"}
           {:name "collector_entity_id" :type "i32" :getter "Get the entity ID of the person picking up the item" :read "varint"}
           {:name "item_count" :type "i32" :getter "Get how many items were picked up" :read "varint"}]}
 {:name "EntityTeleport"
- :id 80
+ :id 87
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID of the entity teleported" :read "varint"}
           {:name "x" :type "f64" :getter "Get the X coordinate the entity moved to"}
           {:name "y" :type "f64" :getter "Get the Y coordinate the entity moved to"}
@@ -724,24 +758,24 @@
           {:name "pitch" :type "i8" :getter "Get the (absolute) pitch"}
           {:name "on_ground" :type "bool" :getter "Get whether the entity is now on the ground"}]}
 {:name "Advancements"
- :id 81
+ :id 88
  :fields [{:name "data" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the raw data for the packet. Parsing it is out of the scope of this library"}]}
 {:name "EntityProperties"
- :id 82
+ :id 89
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "data" :type "Vec<u8>" :getter "Get the raw data for this packet. This library does not attempt to parse the packet" :read "bytearray_to_end"}]}
 {:name "EntityEffect"
- :id 83
+ :id 90
  :fields [{:name "entity_id" :type "i32" :getter "Get the entity ID" :read "varint"}
           {:name "effect_id" :type "u8" :getter "Get the raw effect ID integer enum"}
           {:name "amplifier" :type "i8" :getter "Get the amplifier = effect level - 1"}
           {:name "duration" :type "i32" :getter "Get the duration of the effect in seconds" :read "varint"}
           {:name "flags" :type "u8" :getter "Get the raw flags byte"}]}
 {:name "DeclareRecipes"
- :id 84
+ :id 91
  :fields [{:name "data" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the raw packet data. This packet is not attempted serialized by ozelot"}]}
 {:name "Tags"
- :id 85
+ :id 92
  ; We could probably serialize this packet
  :fields [{:name "data" :type "Vec<u8>" :read "bytearray_to_end" :getter "Get the raw packet data. This packet is not attempted serialized by ozelot"}]}
 ]}})


use destructuring to simplify `record-fact-existence` a little

--- src/midje/ideas/compendium.clj
+++ src/midje/ideas/compendium.clj
@@ -58,13 +58,12 @@

 ;; I must be brain-dead, because this code has got to be way too complicated.
 (defn record-fact-existence [function]
-  (let [metadata (meta function)
-        fact-namespace (:midje/namespace metadata)]
-    (intern 'midje.ideas.compendium (:midje/true-name metadata) function)
-    (when (contains? metadata :midje/name)
+  (let [{fact-namespace :midje/namespace true-name :midje/true-name midje-name :midje/name} (meta function)]
+    (intern 'midje.ideas.compendium true-name function)
+    (when midje-name
       (let [same-namespace-functions (namespace-facts fact-namespace)
             without-old (remove (fn [f]
-                                  (= (:midje/name metadata) (:midje/name (meta f))))
+                                  (= midje-name (:midje/name (meta f))))
                                 same-namespace-functions)]
         (swap! by-namespace-compendium
                assoc fact-namespace without-old)))


Rename dotest to spec-do

Rename dotest to spec-do

Is this macro even necessary?  Could just use
ordinary "do" inside "is" or "given"

--- src/main/clojure/com/stuartsierra/lazytest.clj
+++ src/main/clojure/com/stuartsierra/lazytest.clj
@@ -279,7 +279,7 @@
        ~(when (:name m) `(intern *ns* '~(:name m) ~sym))
        ~sym)))

-(defmacro dotest
+(defmacro spec-do
   "Creates an assertion function consisting of arbitrary code.
   Passes if it does not throw an exception.  Use assert for value
   tests.
@@ -292,7 +292,7 @@
   [& decl]
   (let [[m decl] (attributes decl)
         m (assoc m :line (:line (meta &form))
-                 :generator `dotest
+                 :generator `spec-do
                  :form &form)
         bindings (first decl)
         body (next decl)


Fix NPE in type-pagination

Fix NPE in type-pagination

--- src/multiplex/views/layout.clj
+++ src/multiplex/views/layout.clj
@@ -15,26 +15,26 @@

 (parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))

+(defn phelper [type params]
+  (let [p (util/int-or-default (:page params) 1)
+        l (util/int-or-default (:limit params) config/default-limit)]
+    (util/type-pagination type p l)))
+
 (defn render [template & [params]]
   (let [uid (util/int-or-default (:uid (:post params)) 0)
         theme (if (> uid 0)(:theme (nth config/user-data uid)) (:theme config-fallback))
         cfg (assoc (or config/multiplex config-fallback) :theme theme)
         user-link (if-let [host (util/is-custom-host)] host (:page-url config/multiplex))
-        type-navi-link (util/type-pagination "link" (:page params) (:limit params))
-        type-navi-text (util/type-pagination "text" (:page params) (:limit params))
-        type-navi-image (util/type-pagination "image" (:page params) (:limit params))
-        type-navi-audio (util/type-pagination "audio" (:page params) (:limit params))
-        type-navi-video (util/type-pagination "video" (:page params) (:limit params))
         page-title (if-let [x (:title (:post params))] x (:page-title cfg))
         page-header (if-let [x (:title (:post params))] x (str (:username (:post params)) "'s multiplex" ))]
     (parser/render-file (str template-path template)
                         (assoc params :context (:context *request*)
                                       :page-header page-header
                                       :page-title page-title
-                                      :type-navi-link type-navi-link
-                                      :type-navi-text type-navi-text
-                                      :type-navi-image type-navi-image
-                                      :type-navi-audio type-navi-audio
-                                      :type-navi-video type-navi-video
+                                      :type-navi-link (phelper "link" params)
+                                      :type-navi-text (phelper "text" params)
+                                      :type-navi-image (phelper "image" params)
+                                      :type-navi-audio (phelper "audio" params)
+                                      :type-navi-video (phelper "video" params)
                                       :user-link "/"
                                       :multiplex cfg))))


Remove not needed functions, fix typo.

Remove not needed functions, fix typo.

--- src/oc/storage/api/entries.clj
+++ src/oc/storage/api/entries.clj
@@ -589,40 +589,6 @@
       (timbre/errorf "Failed removing label %s to entry %s by user %s" label-slug-or-uuid (-> ctx :existing-entry :uuid) (-> ctx :user :user-id))
       false)))

-(defn- add-labels [conn ctx label-uuids entry-for]
-  (timbre/infof "Adding labels %s by user %s to entry %s" label-uuids (-> ctx :user :user-id) entry-for)
-  (if-let* [org (:existing-org ctx)
-            board (:existing-board ctx)
-            entry (:existing-entry ctx)
-            user (:user ctx)]
-    (if-let [updated-entry (entry-res/add-labels! conn (:uuid entry) label-uuids user)]
-      (do
-        (timbre/debugf "Labels %s added by user %s on entry %s" label-uuids (-> ctx :user :user-id) (:uuid entry))
-        {:updated-entry (api-common/rep updated-entry)})
-      (do
-        (timbre/infof "Labels not added, it probably means the entry %s already has %s" (:uuid entry) label-uuids)
-        {:existing-entry (api-common/rep entry)}))
-    (do
-      (timbre/errorf "Failed adding labels %s to entry %s by user %s" label-uuids (-> ctx :existing-entry :uuid) (-> ctx :user :user-id))
-      false)))
-
-(defn- remove-labels [conn ctx label-uuids entry-for]
-  (timbre/infof "Removing labels %s by user %s to entry %s" label-uuids (-> ctx :user :user-id) entry-for)
-  (if-let* [org (:existing-org ctx)
-            board (:existing-board ctx)
-            entry (:existing-entry ctx)
-            user (:user ctx)]
-    (if-let [updated-entry (entry-res/remove-labels! conn (:uuid entry) label-uuids user)]
-      (do
-        (timbre/debugf "Labels %s removed by user %s on entry %s" label-uuids (-> ctx :user :user-id) (:uuid entry))
-        {:updated-entry (api-common/rep updated-entry)})
-      (do
-        (timbre/infof "Label not removed, it probably means the entry %s already has %s" (:uuid entry) label-uuids)
-        {:existing-entry (api-common/rep entry)}))
-    (do
-      (timbre/errorf "Failed adding labels %s to entry %s by user %s" label-uuids (-> ctx :existing-entry :uuid) (-> ctx :user :user-id))
-      false)))
-
 (defn- toggle-label-uuids [conn ctx entry-for]
   (let [existing-entry (:existing-entry ctx)
         user (:user ctx)
@@ -630,11 +596,11 @@
     (when (seq add-label-uuids)
       (timbre/infof "Adding labels %s to entry %s by user %s" add-label-uuids entry-for (:user-id user))
       (entry-res/add-labels! conn (:uuid existing-entry) add-label-uuids user))
-    (when (seq add-label-uuids)
+    (when (seq remove-label-uuids)
       (timbre/infof "Removing labels %s to entry %s by user %s" remove-label-uuids entry-for (:user-id user))
-      (entry-res/add-labels! conn (:uuid existing-entry) add-label-uuids user))
-    ;; Return original entry
-    {:updated-labels (entry-res/get-entry conn (:uuid existing-entry))}))
+      (entry-res/remove-labels! conn (:uuid existing-entry) remove-label-uuids user))
+    ;; Return the updated entry
+    {:updated-entry (entry-res/get-entry conn (:uuid existing-entry))}))

 ;; ----- Resources - see: http://clojure-liberator.github.io/liberator/assets/img/decision-graph.svg

@@ -1254,7 +1220,7 @@
         [org-slug board-slug entry-uuid]
         (pool/with-pool [conn db-pool]
           (toggle-labels conn org-slug board-slug entry-uuid)))
-      ;; Single labels
+      ;; Single label
       (ANY (entry-urls/label ":org-slug" ":board-slug" ":entry-uuid" ":label-slug-or-uuid")
         [org-slug board-slug entry-uuid label-slug-or-uuid]
         (pool/with-pool [conn db-pool]


Handle ZK connection loss with restart

Handle ZK connection loss with restart

--- src/onyx/plugin/bookkeeper.clj
+++ src/onyx/plugin/bookkeeper.clj
@@ -17,7 +17,7 @@
             [onyx.peer.operation :refer [kw->fn]]
             [onyx.types :refer [dec-count! inc-count!]]
             [taoensso.timbre :refer [info error debug fatal]])
-  (:import [org.apache.zookeeper KeeperException$BadVersionException]
+  (:import [org.apache.zookeeper KeeperException$BadVersionException KeeperException$ConnectionLossException]
            [org.apache.bookkeeper.client LedgerHandle LedgerEntry BookKeeper BKException$Code
             BookKeeper$DigestType AsyncCallback$AddCallback]))

@@ -294,8 +294,14 @@
                           commit-ch
                           shutdown-ch)))

+(defn read-handle-exception [event lifecycle lf-kw exception]
+  (cond (= exception org.apache.zookeeper.KeeperException$ConnectionLossException)
+        :restart
+        :else :defer))
+
 (def read-ledgers-calls
   {:lifecycle/before-task-start inject-read-ledgers-resources
+   :lifecycle/handle-exception read-handle-exception
    :lifecycle/after-task-stop close-read-ledgers-resources})

 ;;;;;;;;;;;;;
@@ -312,8 +318,14 @@
   (.close client)
   {})

+(defn write-handle-exception [event lifecycle lf-kw exception]
+  (cond (= exception org.apache.zookeeper.KeeperException$ConnectionLossException)
+        :restart
+        :else :defer))
+
 (def write-ledger-calls
   {:lifecycle/before-task-start inject-write-ledger-resources
+   :lifecycle/handle-exception write-handle-exception
    :lifecycle/after-task-stop close-write-ledger-resources})

 (def HandleWriteCallback