update sample-data importer to pass conn argument

--- src/open_company/util/sample_data.clj
+++ src/open_company/util/sample_data.clj
@@ -3,6 +3,7 @@
   (:require [clojure.string :as s]
             [clojure.tools.cli :refer (parse-opts)]
             [defun :refer (defun-)]
+            [open-company.db.pool :as db]
             [open-company.resources.common :as common]
             [open-company.resources.company :as company]
             [open-company.resources.section :as section])
@@ -16,9 +17,9 @@

 (defun- import-sections
   "Add each section to the company recursively."
-  ([_company-slug _sections :guard empty? _org-id] true)
+  ([conn _company-slug _sections :guard empty? _org-id] true)

-  ([company-slug sections org-id]
+  ([conn company-slug sections org-id]
   (let [section (first sections)
         section-name (:section-name section)
         timestamp (:timestamp section)
@@ -26,39 +27,40 @@
         message (str "'" section-name "' at " timestamp " by " (:name author) ".")]
     (println (str "Creating " message))
     (if
-      (section/put-section company-slug section-name (:section section) (assoc author :org-id org-id) timestamp)
+      (section/put-section conn company-slug section-name (:section section) (assoc author :org-id org-id) timestamp)
       (println (str "SUCCESS: created " message))
       (println (str "FAILURE: creating " message))))
-  (recur company-slug (rest sections) org-id)))
+  (recur conn company-slug (rest sections) org-id)))

 (defn- import-sections-map
   "Update the company with the specified slug with the specified :sections map."
-  [slug sections]
+  [conn slug sections]
   (println (str "Updating company sections for '" slug "'."))
-  (if-let [original-company (common/read-resource company/table-name slug)]
-    (common/update-resource company/table-name :slug original-company (assoc original-company :sections sections))))
+  (if-let [original-company (common/read-resource conn company/table-name slug)]
+    (common/update-resource conn company/table-name :slug original-company (assoc original-company :sections sections))))

 ;; ----- Company import -----

-(defn import-company [options data]
+(defn import-company [conn options data]
   (let [company (:company data)
         slug (:slug company)
         delete (:delete options)
         author (:author company)
         org-id (:org-id company)]
-    (when (and delete (company/get-company slug))
+    (when (and delete (company/get-company conn slug))
       (println (str "Deleting company '" slug "'."))
-      (company/delete-company slug))
+      (company/delete-company conn slug))
     (when-not delete
-      (when (company/get-company slug)
+      (when (company/get-company conn slug)
         (exit 1 (str "A company for '" slug "' already exists. Use the -d flag to delete the company on import."))))
     (println (str "Creating company '" slug "' by " (:name author)"."))
     (company/create-company!
+     conn
      (company/->company
       (dissoc company :author :timestamp :sections :org-id)
       (assoc author :org-id org-id)))
-    (import-sections slug (:sections data) org-id)
-    (import-sections-map slug (:sections company)))
+    (import-sections conn slug (:sections data) org-id)
+    (import-sections-map conn slug (:sections company)))
   (println "\nImport complete!\n"))

 ;; ----- CLI -----
@@ -101,6 +103,7 @@
     ;; Get the list of files to import
     (try
       (let [arg (first arguments)
+            conn (db/init-conn)
             edn-file #".*\.edn$"
             filenames (if (re-matches edn-file arg)
                         [arg] ; they specified just 1 file
@@ -109,7 +112,7 @@
         (doseq [filename filenames]
           (let [data (read-string (slurp filename))]
             (if (and (map? data) (:company data) (:sections data))
-              (import-company options data)
+              (import-company conn options data)
               (exit 1 (data-msg))))))
       (catch Exception e
         (println e)


jobs/web/assignids.clj: use text format

jobs/web/assignids.clj: use text format

--- src/org/altlaw/jobs/web/assignids.clj
+++ src/org/altlaw/jobs/web/assignids.clj
@@ -55,5 +55,7 @@
     (.setReducerClass job org.altlaw.jobs.web.assignids_reducer)
     (.setNumReduceTasks job 1)
     (.setJobName job "web.assignids")
+    (.setInputFormat job KeyValueTextInputFormat)
+    (.setOutputFormat job TextOutputFormat)
     (JobClient/runJob job))
   0)


CMR-4396 - Support non-request-context data calls.

--- search-app/src/cmr/search/site/data.clj
+++ search-app/src/cmr/search/site/data.clj
@@ -28,8 +28,27 @@
   (case tag
     "gov.nasa.eosdis" "EOSDIS"))

-(defn collection-data
+(defmulti get-providers
+  "Get the providers, based on contextual data."
+  :execution-context)
+
+(defmethod get-providers :cli
+  [context]
+  (:providers context))
+
+(defmethod get-providers :default
+  [context]
+  (mdb/get-providers context))
+
+(defmulti collection-data
   "Get the collection data associated with a provider and tag."
+  (fn [context & args] (:execution-context context)))
+
+(defmethod collection-data :cli
+  [context tag provider-id]
+  (:collections context))
+
+(defmethod collection-data :default
   [context tag provider-id]
   (as-> {:tag-key tag
          :provider provider-id
@@ -120,17 +139,17 @@
 ;;; Page data functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn base-page
+(defmulti base-page
   "Data that all app pages have in common."
+  :execution-context)
+
+(defmethod base-page :cli
+  [context]
+  (assoc (common-data/base-static) :app-title "CMR Search"))
+
+(defmethod base-page :default
   [context]
   (assoc (common-data/base-page context) :app-title "CMR Search"))
-
-(defn base-static
-  "Data that all static pages have in common.
-
-  Note that static pages don't have any context."
-  []
-  (assoc (common-data/base-static) :app-title "CMR Search"))

 (defn get-directory-links
   "Provide the list of links that will be rendered on the top-level directory
@@ -142,10 +161,9 @@
              :text "EOSDIS Collections"}]}))

 (defn get-eosdis-directory-links
-  "Generate the data necessary to render EOSDIS directory page links."
   [context]
   (->> context
-       (mdb/get-providers)
+       (get-providers)
        (providers-data context "gov.nasa.eosdis")
        (hash-map :providers)
        (merge (base-page context))))


Minor tweaks to error handling.

Minor tweaks to error handling.

--- src/prod/clj/com/potetm/tire_iron.clj
+++ src/prod/clj/com/potetm/tire_iron.clj
@@ -242,6 +242,9 @@

 (defn html-async-init-error? [ex-i]
   (let [{{:keys [value] :as e} :error} (ex-data ex-i)]
+    ;; I tested this when I used "goog.net.jsloader.loadMany". These
+    ;; errors are still fairly useful for posterity methinks.
+
     ;; chrome
     ;;  "TypeError: Cannot read property 'loadMany' of undefined"
     ;; firefox
@@ -253,12 +256,10 @@
     ;; ie10
     ;;  "TypeError: Unable to get property 'loadMany' of undefined or null reference"
     (when value
-      (or (and (str/includes? value "TypeError")
-               (or (str/includes? value "loadMany")
-                   (str/includes? value "goog.net.jsloader")
-                   (str/includes? value "tire_iron_name_to_path__")
-                   (str/includes? value "tire_iron_scriptLoadingDeferred_")
-                   (str/includes? value "tire_iron_loadMany__")))))))
+      (and (str/includes? value "TypeError")
+           (or (str/includes? value "tire_iron_name_to_path__")
+               (str/includes? value "tire_iron_scriptLoadingDeferred_")
+               (str/includes? value "tire_iron_loadMany__"))))))

 (defrecord DomAsyncRefresher []
   IRefresh
@@ -345,7 +346,7 @@
                           "})();")))
       (catch ExceptionInfo ei
         (if (html-async-init-error? ei)
-          (do (prn :re-initializing)
+          (do (comment (prn :re-initializing))
               (-initialize this opts)
               (eval-script repl-env
                            (str "(function() {\n"


add new :field->field option to sel macro

--- src/metabase/db.clj
+++ src/metabase/db.clj
@@ -303,6 +303,10 @@
     ;; Return a map of field value -> ID. Duplicates will be discarded!
     (sel :many :field->id [User :first_name])
       -> {\"Cam\" 1, \"Sameer\" 2}
+
+    ;; Return a map of field value -> field value.
+    (sel :many :field->field [User :first_name :last_name])
+      -> {\"Cam\" \"Saul\", \"Rasta\" \"Toucan\", ...}

     ;; Return a map of field value -> *entire* object. Duplicates will be discarded!
     (sel :many :field->obj [Table :name] :db_id 1)
@@ -357,6 +361,11 @@
                            (map (fn [{id# :id field-val# field#}]
                                   {field-val# id#}))
                            (into {})))
+        :field->field `(let [[entity# field1# field2#] ~entity]
+                         (->> (sel :many entity# ~@forms)
+                              (map (fn [obj#]
+                                     {(field1# obj#) (field2# obj#)}))
+                              (into {})))
         :field->obj `(let [[entity# field#] ~entity]
                        (->> (sel :many entity# ~@forms)
                             (map (fn [obj#]


Preparing proto-repl-sayid library for initial push to clojars.

--- proto-repl-sayid-lib/project.clj
+++ proto-repl-sayid-lib/project.clj
@@ -1,6 +1,8 @@
-(defproject proto-repl-sayid "0.1.0-SNAPSHOT"
+(defproject proto-repl-sayid "0.1.0"
   :description "Proto REPL Sayid integration that provides a visual call stack and debugging"
   :url "https://github.com/jasongilman/proto-repl-sayid"
+  :license {:name "MIT"
+            :url "https://opensource.org/licenses/MIT"}
   :dependencies [[org.clojure/clojure "1.8.0"]
                  [proto-repl "0.3.1"]
                  [com.billpiel/sayid "0.0.10"]]


CMR-3048: Removed debug output

CMR-3048: Removed debug output

--- indexer-app/src/cmr/indexer/services/event_handler.clj
+++ indexer-app/src/cmr/indexer/services/event_handler.clj
@@ -15,8 +15,7 @@
     (keyword (:action msg))))

 (defmethod handle-ingest-event :default
-  [context all-revisions-index? msg]
-  (warn "I'm ignoring this message" msg))
+  [_ _ _])
 ;; Default ignores the ingest event. There may be ingest events we don't care about.

 (defmethod handle-ingest-event :provider-collection-reindexing


Ready for next release

Ready for next release

--- lein-template/project.clj
+++ lein-template/project.clj
@@ -1,7 +1,7 @@
 ;; Copyright © 2014 JUXT LTD.

 ;; We call this project modular to make the invocation: lein new modular appname
-(defproject modular/lein-template "0.6.9"
+(defproject modular/lein-template "0.6.10"
   :description "Leiningen template for a full-featured component based app using modular extensions."
   :license {:name "The MIT License"
             :url "http://opensource.org/licenses/MIT"}


Ready to deploy lein-template 0.5.2

Ready to deploy lein-template 0.5.2

--- lein-template/project.clj
+++ lein-template/project.clj
@@ -1,7 +1,7 @@
 ;; Copyright © 2014 JUXT LTD.

 ;; We call this project modular to make the invocation: lein new modular appname
-(defproject modular/lein-template "0.5.2-SNAPSHOT"
+(defproject modular/lein-template "0.5.2"
   :description "Leiningen template for a full-featured component based app using modular extensions."
   :license {:name "The MIT License"
             :url "http://opensource.org/licenses/MIT"}


Simplify get-class-name

Simplify get-class-name

--- src/refactor_nrepl/ns/dependencies.clj
+++ src/refactor_nrepl/ns/dependencies.clj
@@ -113,21 +113,10 @@
   (some-> (get-ns-component ns-form :import) extract-imports
           flatten))

-(defn- class-op?
-  [op]
-  (or (= op :static-call)
-      (= op :const)
-      (= op :static-field)
-      (= op :new)))
-
-(defn- get-class-name [{:keys [op class type val children] :as node}]
-  (when-not children
-    (try
-      (cond
-        (and (class-op? op) (:type :class)) (.getName val)
-        (and class (not= op :import)) (str (.getName class)))
-      (catch Exception e
-        (println e)))))
+(defn- get-class-name [{:keys [op class children] :as node}]
+  (when (and (and class (not= op :import))
+             (not children))
+    (str (.getName class))))

 (defn- get-var-name [node]
   (some-> node


Update test for explicit starting room code.

--- test/isla/test/story.clj
+++ test/isla/test/story.clj
@@ -33,7 +33,8 @@
 (deftest test-look-general
   (let [summary "The floors are made of marble."
         story-str (str "palace is a room
-                        palace summary is '" summary "'")
+                        palace summary is '" summary "'
+                        my room is palace")
         story (init-story story-str)]
     (is (= (run-command story "look")
            summary))))


turn of js

turn of js

--- src/site/layout.clj
+++ src/site/layout.clj
@@ -39,7 +39,7 @@
     [:div#main [:div#wrap cnt]]
     (footer)
     [:script {:type "text/javascript" :src (asset-path "jquery.min.js")}]
-    [:script {:type "text/javascript" :src (asset-path "instant.js")}]]])
+    #_[:script {:type "text/javascript" :src (asset-path "instant.js")}]]])


clien receive via core.async

clien receive via core.async

--- src/clj/rksm/websocket_test/client.clj
+++ src/clj/rksm/websocket_test/client.clj
@@ -1,10 +1,22 @@
 (ns rksm.websocket-test.client
+  (:refer-clojure :exclude [send])
   (:require [gniazdo.core :as ws]
             [clojure.string :as s]
             [clojure.data.json :as json]
             [rksm.websocket-test.com :as com]
-            [clojure.core.async :as async])
+            [clojure.core.async :as async :refer [>! >!! <! <!! chan go go-loop sub pub close!]])
   (:import (java.util UUID)))
+
+(declare send!)
+
+(defprotocol IConnection
+  (send [this msg]))
+
+(defrecord Connection [url id tracker-id ws]
+  IConnection
+  (send [this msg] (send! this msg)))
+
+; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 (defonce connections (atom {}))

@@ -18,7 +30,24 @@
 ; (ws/close [conn])
 ; (ws/client [] [uri])

-(defn create-ws-connection
+(defn- receive-msg
+  "Will
+  1. parse msg-string into map
+  2. lookup channels registered under the in-response-to message id
+  3. if expect-more-responses is falsish remove and close channel"
+  [ws-chan msg-string]
+  (let [msg (json/read-str msg-string :key-fn keyword)]
+    (>!! ws-chan msg))
+;   (try (let [{:keys [in-response-to expect-more-responses], :as msg}
+;              (json/read-str msg-string :key-fn keyword)]
+;          (when-let [c (get @receive-channels in-response-to)]
+;           (>!! c msg)
+;           (if-not expect-more-responses
+;              (remove-channel! in-response-to))))
+;     (catch Exception e (println "Error receiving message " msg-string)))
+  )
+
+(defn- create-ws-connection
   "options to ws/connect:
   :on-connect – a unary function called after the connection has been
   established. The handler is a Session instance.
@@ -36,73 +65,63 @@
   :client – an optional WebSocketClient instance to be used for connection
   establishment; by default, a new one is created internally on each call.
   gniazdo.core/connect returns an opaque representation of the connection."
-  [url on-receive]
+  [url ws-chan]
   (let [url (s/replace url #"^http" "ws")]
     (ws/connect url
-                :on-receive on-receive
+                :on-receive (fn [msg-string]
+                              (let [msg (json/read-str msg-string :key-fn keyword)]
+                                (>!! ws-chan {:message msg})))
+                :on-error (fn [err] (>!! ws-chan {:error err}))
+                :on-close (fn [err] (close! ws-chan))
                 :headers {"sec-websocket-protocol" ["lively-json"]})))

-(defn ws-connect!
-  [{:keys [host port path protocol on-receive],
+(defn- ws-connect!
+  [{:keys [host port path protocol],
     :or {host "0.0.0.0", port 8080, path "/ws", protocol "ws"}}]
-  (let [url (str protocol "://" host ":" port path)]
-    (create-ws-connection url on-receive)))
-
-(declare receive-msg)
+  (let [url (str protocol "://" host ":" port path)
+        ws-chan (chan)
+        recv-chan (pub ws-chan (comp :in-response-to :message))]
+    {:socket (create-ws-connection url ws-chan)
+     :chan ws-chan
+     :receiver recv-chan}))

 (defn ensure-connection!
   [& {:keys [id], :as opts}]
   (if-let [c (find-connection id)]
     c
     (let [id (str (UUID/randomUUID))
-          on-receive (fn [msg] (if-let [c (find-connection id)] (receive-msg c msg)))
-          c {:id id, :ws (ws-connect! (assoc opts :on-receive on-receive))}]
+          c {:id id, :ws (ws-connect! opts)}]
       (swap! connections assoc id c)
       c)))

 (defn stop!
   [{:keys [ws id] :as con}]
-  (if ws (ws/close ws))
+  (some-> ws :socket ws/close)
   (swap! connections dissoc id))

 (defn stop-all!
   []
   (doseq [[_ c] @connections] (stop! c)))

-(defonce receive-channels (atom {}))
-
-(defn remove-channel!
-  [id]
-  (when-let [c (get @receive-channels id)]
-    (async/close! c)
-    (swap! receive-channels dissoc id)))
-
-(defn remove-all-channels!
-  []
-  (doseq [[id _] @receive-channels]
-    (remove-channel! id)))
-
-(defn receive-msg
-  "Will
-  1. parse msg-string into map
-  2. lookup channels registered under the in-response-to message id
-  3. if expect-more-responses is falsish remove and close channel"
-  [{sender :id, :as con} msg-string]
-  (try (let [{:keys [in-response-to expect-more-responses], :as msg}
-             (json/read-str msg-string :key-fn keyword)]
-         (when-let [c (get @receive-channels in-response-to)]
-           (async/>!! c msg)
-           (if-not expect-more-responses
-             (remove-channel! in-response-to))))
-    (catch Exception e (println "Error receiving message " msg-string))))
-
 (defn send!
+  "sends message via websocket and returns a channel that will receive answer
+  messages matching the message id of the sent message. client facing channel
+  will close when there are no more answers to be expected."
   [{ws :ws, :as con} msg]
-  (let [c (async/chan)
-        {msg-id :id} (com/send! #(ws/send-msg ws (json/write-str %)) con msg)]
-    (swap! receive-channels assoc msg-id c)
-    c))
+  (let [{msg-id :id} (com/send! #(ws/send-msg (:socket ws) (json/write-str %)) con msg)
+        client-chan (chan)
+        sub-chan (sub (:receiver ws) msg-id (chan))
+        close (fn [] (close! sub-chan) (close! client-chan))]
+    (go-loop []
+      (let [{:keys [message error] :as msg} (<! sub-chan)]
+        (if msg (>! client-chan msg))
+        (cond
+          (nil? msg) (close)
+          error (close)
+          (not (:expect-more-responses message)) (close)
+          :default (recur))))
+    client-chan))

 (defn answer!
  [{ws :ws, :as con} msg data]
-  (com/answer! #(ws/send-msg ws (json/write-str %)) con msg data))
+  (com/answer! #(ws/send-msg (:socket ws) (json/write-str %)) con msg data))


Only add traps to underground temple levels

--- src/cljc/robinson/dungeons/temple.cljc
+++ src/cljc/robinson/dungeons/temple.cljc
@@ -240,7 +240,8 @@
                          [x y cell]))
                       cellsxy)
         cellsxy (add-room-features level cellsxy)
-        cellsxy (if trap-room?
+        cellsxy (if (and trap-room?
+                         (pos? level))
                   (add-trap min-x min-y max-x max-y cellsxy)
                   cellsxy)]
    cellsxy))


refactor evidence, fix evidence list

refactor evidence, fix evidence list

--- src/cljs/salava/badge/ui/evidence.cljs
+++ src/cljs/salava/badge/ui/evidence.cljs
@@ -6,13 +6,75 @@
             [salava.core.ui.helper :refer [plugin-fun path-for hyperlink base-url]]
             [salava.core.ui.ajax-utils :as ajax]
             [salava.core.time :refer [date-from-unix-time]]
-            [clojure.string :refer [blank? includes? split trim]]
+            [clojure.string :refer [blank? includes? split trim starts-with?]]
             [salava.file.icons :refer [file-icon]]
             [salava.file.ui.my :refer [send-file]]))

 (defn url? [s]
   (when-not (blank? s)
     (not (blank? (re-find #"^http" (str (trim s)))))))
+
+
+(defn toggle-input-mode [key state]
+  (let [key-atom (cursor state [:input_mode])]
+    (do (reset! key-atom nil) (reset! key-atom key))))
+
+(defn delete-evidence! [id data state init-data]
+  (let [init-settings (first (plugin-fun (session/get :plugins) "modal" "show_settings_dialog"))]
+    (ajax/DELETE
+      (path-for (str "/obpv1/badge/evidence/" id))
+      { :params {:user_badge_id (:id data)}
+        :handler (fn [r]
+                   (when (= "success" (:status r))
+                     (init-settings (:id data) state init-data "settings")))})))
+
+
+(defn init-resources [key resource-atom]
+  (let [url (case key
+              :page_input "/obpv1/page"
+              :file_input "/obpv1/file")]
+    (ajax/GET
+      (path-for url true)
+      {:handler (fn [data]
+                  (reset! resource-atom data))})))
+
+(defn init-evidence-form [evidence state show-url?]
+  (let [ {:keys [id name url description]} evidence
+         evidence { :id (:id evidence)
+                    :name (:name evidence)
+                    :url (:url evidence)
+                    :description (:description evidence)}]
+    (swap! state assoc :evidence evidence)))
+
+
+(defn set-page-visibility-to-private [page-id]
+  (ajax/POST
+    (path-for (str "/obpv1/page/toggle_visibility/" page-id))
+    {:params {:visibility "public"}
+     :handler (fn [data]
+                (prn data))}))
+
+(defn save-badge-evidence [data state init-data]
+  (let [{:keys [id name description url visibility resource_id]} (:evidence @state)
+        badge-id (:id data)
+        init-settings (first (plugin-fun (session/get :plugins) "modal" "show_settings_dialog"))]
+    (swap! state assoc :evidence {:message nil})
+    (if (blank? url)
+      (swap! state assoc :evidence {:message [:div.alert.alert-warning [:p "Resource field can't be empty!"]]})
+
+      (do
+        (if (= "private" visibility) (set-page-visibility-to-private resource_id))
+        (ajax/POST
+          (path-for (str "/obpv1/badge/evidence/" badge-id))
+          {:params {:id id
+                    :name (if name (trim name))
+                    :description description
+                    :url (if url (trim url))}
+           :handler (fn [resp]
+                      (when (= "success" (:status resp))
+                        (init-settings (:id data) state init-data "settings")))})))))
+
+;;;;

 (defn input [input-data textarea?]
   (let [{:keys [name atom placeholder type error-message-atom rows cols]} input-data]
@@ -29,62 +91,40 @@
       :rows rows
       :cols cols}]))

-
-
-(defn toggle-input-mode [key state]
-  (let [key-atom (cursor state [:input_mode])]
-    (if (= key @key-atom) (reset! key-atom nil) (do (reset! key-atom nil) (reset! key-atom key)))))
-
-
-(defn init-resources [key resource-atom]
-  (let [url (case key
-              :page_input "/obpv1/page"
-              :file_input "/obpv1/file")]
-    (ajax/GET
-      (path-for url true)
-      {:handler (fn [data]
-                  (reset! resource-atom data)
-                  )})))
-
-
-(defn remove-url [url coll state]
-  (swap! state assoc-in [:evidence :urls] (remove #(= url %) @coll)))
-
-(defn grid-element [element-data state key]
-  (let [{:keys [id name path visibility mtime badges ctime mime_type]} element-data
+(defn evidence-icon [evidence_type]
+  (let [{:keys [type mime_type]} evidence_type]
+    [:div.evidence-icon
+     (case type
+       "page" [:i.fa.fa-file-text-o]
+       "url" [:i.fa.fa-link]
+       "file" [:i {:class (str "fa " (file-icon mime_type)) } ]
+       [:i.fa.fa-link])]))
+
+(defn grid-element [element-data state key data init-data]
+  (let [{:keys [id name path description visibility mtime badges ctime mime_type]} element-data
         value (case key
                 :page_input (str (session/get :site-url) (path-for (str "/page/view/" id)))
                 :file_input (str (session/get :site-url) "/" path)
                 nil)
         evidence-url-atom (cursor state [:evidence :url])
-        show-url? (cursor state [:evidence :show_url])
-        resource-input-mode (cursor state [:input_mode])
-        update-page-visibility ()]
-    (prn visibility)
-   (when (= "private" visibility) (swap! state assoc :evidence {:update-page-visibility id}))
-    [:div.radio
-     [:label
-      [:input { :name "opt"
-                :type "radio"
-                :value value
-                :on-change #(do
-                              (reset! evidence-url-atom (.-target.value %))
-                              (reset! resource-input-mode nil)
-                              (reset! show-url? true))}]
+        evidence-name-atom (cursor state [:evidence :name])
+        evidence-description-atom (cursor state [:evidence :description])
+        evidence-visibility-atom (cursor state [:evidence :visibility])
+        resource-id-atom (cursor state [:evidence :resource_id])]
+    [:div
+     [:a.resource-link {:href "#"
+                        :on-click #(do
+                                     (.preventDefault %)
+                                     (reset! evidence-url-atom value)
+                                     (reset! evidence-name-atom name)
+                                     (reset! evidence-description-atom description)
+                                     (reset! evidence-visibility-atom visibility)
+                                     (reset! resource-id-atom id)) }
       (case key
-        :page_input [:a {:href "#" :on-click #(do
-                                                (.preventDefault %)
-                                                (mo/open-modal [:page :view] {:page-id id}))} name]
-
-        :file_input [:div [:i {:style {:margin-right "10px"}
-                               :class (str "file-icon-large fa " (file-icon mime_type))}]
-                     [:a {:href (str "/" path) :target "_blank"} name]])]]))
-
-
-
-
-(defn toggle-visible-area [visible-area-atom key]
-  (if (= key @visible-area-atom) (reset! visible-area-atom nil) (reset! visible-area-atom key)))
+        :page_input [:div.resource  [:i.fa.fa-file-text-o] name]
+        :file_input [:div.resource [:i {:style {:margin-right "10px"}
+                                        :class (str "file-icon-large fa " (file-icon mime_type))}]
+                     name])]]))

 (defn upload-status [status title message]
   [:div
@@ -96,8 +136,7 @@
             (translate-text message)]
            [:div
             [:i {:class "fa fa-cog fa-spin fa-2x"}]
-            [:span " " (translate-text message)]])]
-   ])
+            [:span " " (translate-text message)]])]])

 (defn upload-file [files-atom state]
   (let [files (:files @files-atom)
@@ -124,89 +163,24 @@
                         )})))

-(defn resources-grid [key resource-atom state]
+(defn resources-grid [key resource-atom state data init-data]
   (let [evidence-url-atom (cursor state [:evidence :url])
-        {:keys[files]} @resource-atom]
-    [:div.resource-upload
-     (if files
-       [:div [:label
-                       [:span [:i.fa.fa-upload] (t :file/Upload) ]
-                       [:input {:id "grid-file-upload"
-                                :type "file"
-                                :name "file"
-                                :on-change #(upload-file resource-atom state)
-                                :style {:display "none"}}]
-                       ]])
-     [:div.col-md-9.resource-container
-      (reduce (fn [r resource]
-                (conj r [grid-element resource state key])
-                ) [:form] (if files files @resource-atom))
-      ]]))
-
-
-(defn init-evidence-form [evidence state show-url?]
-  (let [ {:keys [id name url audience narrative genre description]} evidence
-         evidence { :id (:id evidence)
-                   :name (:name evidence)
-                   :url (:url evidence)
-                   :audience (:audience evidence)
-                   :narrative (:narrative evidence)
-                   :genre (:genre evidence)
-                   :description (:description evidence)
-                   }]
-    (if (every? #(blank? %) (vector name audience narrative genre description))
-      (swap! state assoc :show_form nil)
-      (swap! state assoc :show_form true))
-    (if show-url?
-      (swap! state assoc :evidence (assoc evidence :show_url true :input_mode nil) )
-      (swap! state assoc :evidence evidence))))
-
-(defn save-badge-evidence [data state init-data]
-  (let [{:keys [id name description url update-page-visibility]} (:evidence @state)
-        badge-id (:id data)
-        init-settings (first (plugin-fun (session/get :plugins) "modal" "show_settings_dialog"))]
-    (swap! state assoc :evidence {:message nil})
-    (if (blank? url)
-      (swap! state assoc :evidence {:message [:div.alert.alert-warning [:p "Resource field can't be empty!"]]})
-
-      (ajax/POST
-        (path-for (str "/obpv1/badge/evidence/" badge-id))
-        {:params {:id id
-                  :name (if name (trim name))
-                  :description description
-                  :url (if url (trim url))}
-         :handler (fn [resp]
-                    (when (= "success" (:status resp))
-                      (init-settings (:id data) state init-data "settings"))
-
-
-                    )}))))
-
-(defn selected-url [state init-data]
-  (let [evidence-url-atom (cursor state [:evidence :url])
-        show-url? (cursor state [:evidence :show_url])
-        evidence (cursor state [:evidence])]
-    (fn []
-      (when (and (not (empty? @evidence-url-atom )) @show-url?)
-        [:div.col-md-9
-
-
-         [:button.close {:type "button"
-                         :aria-label "OK"
-                         :on-click #(do
-                                      (.preventDefault %)
-                                      (reset! show-url? false)
-                                      (reset! evidence (assoc @evidence :url nil :show_url false
-                                                         ))
-                                      (init-evidence-form @evidence state false)
-                                      )
-                         }
-          [:span {:aria-hidden "true"
-                  :dangerouslySetInnerHTML {:__html "×"}}]]
-         [:div.selected-url (hyperlink (trim @evidence-url-atom))]]
-        ))))
-
-(defn resource-input [state]
+        {:keys[files]} @resource-atom
+        init-container (case key
+                         :file_input [:div [:label
+                                            [:span [:i.fa.fa-upload] (t :file/Upload) ]
+                                            [:input {:id "grid-file-upload"
+                                                     :type "file"
+                                                     :name "file"
+                                                     :on-change #(upload-file resource-atom state)
+                                                     :style {:display "none"}}]]]
+                         :page_input [:div])]
+    [:div.col-md-9.resource-container
+     (reduce (fn [r resource]
+               (conj r [grid-element resource state key data init-data])
+               ) init-container (if files files @resource-atom))]))
+
+(defn resource-input [data state init-data]
   (let [resource-input-mode (cursor state [:input_mode])
         evidence-url-atom (cursor state [:evidence :url])
         resource-atom (atom {})
@@ -217,34 +191,21 @@
         (case @resource-input-mode
           :file_input (do
                         (init-resources :file_input resource-atom)
-                        [:div [resources-grid :file_input resource-atom state]])
+                        [:div [resources-grid :file_input resource-atom state data init-data]])
           :page_input (do
                         (init-resources :page_input resource-atom)
-                        [:div [resources-grid :page_input resource-atom state]])
-          :url_input [:div {:style {:margin-bottom "10px"}}
-                      [input {:name "evidence-url" :atom evidence-url-atom :type "url"}]
-                      [:button {:type "button"
-                                :class "btn btn-primary"
-                                :disabled (not (url? @evidence-url-atom))
-                                :on-click #(do
-                                             (.preventDefault %)
-                                             (reset! show-url? true)
-                                             (reset! resource-input-mode nil))}
-                       (t :core/Add)]]
+                        [:div [resources-grid :page_input resource-atom state data init-data]])
+          :url_input [:div.resource-container {:style {:margin-bottom "10px"}}
+                      [input {:name "evidence-url" :atom evidence-url-atom :type "url" :placeholder "http://"}]]
           nil)]])))
-

 (defn evidence-form [data state init-data]
   (let [settings-tab (first (plugin-fun (session/get :plugins) "settings" "settings_tab_content"))
         evidence-name-atom (cursor state [:evidence :name])
         evidence-description-atom (cursor state [:evidence :description])
         evidence-url-atom (cursor state [:evidence :url])
-        page-input-enabled? (cursor state [:page_input])
         message (cursor state [:evidence :message])
-        show-url? (cursor state [:evidence :show_url])
-        file-input-enabled? (cursor state [:file_input])
-        resource-input-mode (cursor state [:input_mode])
-        show-form (cursor state [:show_form])
+        input-mode (cursor state [:input_mode])
         {:keys [image_file name]} data]

     [:div {:id "badge-settings" :class "row flip"}
@@ -256,110 +217,113 @@
        [:div.form-horizontal
         [:div.form-group
          [:label.col-md-9.sub-heading "Add evidence resource"]
-         [:div.col-md-9 {:style {:margin-top "10px" :margin-bottom "10px"}}
-          [:div {:style {:float "left"}}
-           [:div {:style {:float "left" :margin-right "10px"}}[:a {:style {:margin "10px"} :href "#"  :on-click #(toggle-input-mode :url_input state)} [:i.fa.fa-link] (t :admin/Url)]]
-           [:div {:style {:float "left" :margin-right "10px"}} [:a {:href "#" :on-click #(do (toggle-input-mode :page_input state)
-                                                                                #_(swap! state assoc :tab [resource-tab data state init-data])
-                                                                                ) } [:i.fa.fa-file] (t :page/Mypages)]]
-           [:div {:style {:float "left"}} [:a {:href "#"
-                                               :on-click #(do
-                                                            (.preventDefault %)
-                                                            (toggle-input-mode :file_input state))
-                                               } [:i.fa.fa-file] (t :page/Files)]]]]]
-
-         [selected-url state init-data]
-         [resource-input state]
-
-        (if @show-form
-          [:div
-           [:div.form-group
-            [:label.col-md-3 "Name"]
-            [:div.col-md-9
-             [input {:name "name" :atom evidence-name-atom :type "text"} nil]]]
-           [:div.form-group
-            [:label.col-md-3 (t :page/Description)]
-            [:div.col-md-9
-             [input {:name "Description" :rows 5 :cols 40 :atom evidence-description-atom } true]]]]
-
-          [:div [:i.fa.fa-plus]
-           [:a {:href "#" :on-click #(do (.preventDefault %) (reset! show-form true))} "Add more info about this evidence"]])
-         [:hr]]
+         [:div.col-md-9.resource-options
+          [:div ;{:style {:float "left"}}
+           [:div [:a {:class (if (= :url_input @input-mode) "active-resource" "")
+                      :href "#"
+                      :on-click #(do
+                                   (.preventDefault %)
+                                   (toggle-input-mode :url_input state))}
+                  [:i.fa.fa-link] (t :admin/Url)]]
+           [:div  [:a {:class (if (= :page_input @input-mode) "active-resource" "")
+                       :href "#"
+                       :on-click #(do
+                                    (.preventDefault %)
+                                    (toggle-input-mode :page_input state)) }
+                   [:i.fa.fa-file-text] (t :page/Mypages)]]
+           [:div  [:a {:class (if (= :file_input @input-mode) "active-resource" "")
+                       :href "#":on-click #(do
+                                             (.preventDefault %)
+                                             (toggle-input-mode :file_input state))
+                       } [:i.fa.fa-files-o] (t :page/Files)]]]]]
+        [resource-input data state init-data]
         [:div
-         [:button {:type         "button"
-                   :class        "btn btn-primary"
-                   :on-click     #(save-badge-evidence data state init-data)}
-          (t :badge/Save)]
+         [:hr]
          [:button {:type "button"
                    :class "btn btn-primary"
-                   :on-click #(do (.preventDefault %) (swap! state assoc :tab [settings-tab (dissoc data :evidence) state init-data] :tab-no 2))}
-          (t :core/Cancel)]]]]]))
-
-(defn delete-evidence! [id data state init-data]
-  (let [init-settings (first (plugin-fun (session/get :plugins) "modal" "show_settings_dialog"))]
-    (ajax/DELETE
-      (path-for (str "/obpv1/badge/evidence/" id))
-      { :params {:user_badge_id (:id data)}
-        :handler (fn [r]
-                   (when (= "success" (:status r))
-                     (init-settings (:id data) state init-data "settings")))})))
+                   :disabled (not (url? @evidence-url-atom))
+                   :on-click #(do
+
+                                (.preventDefault %)
+                                (save-badge-evidence data state init-data))}
+          (t :core/Add)]
+         [:a.cancel {:on-click #(do (.preventDefault %) (swap! state assoc :tab [settings-tab (dissoc data :evidence) state init-data]
+                                                                :tab-no 2
+                                                                :new_input nil))}
+          (t :core/Cancel)]]]]]]))
+
+

 (defn evidence-list [data state init-data]
-  (reduce (fn [r evidence]
-            (let [{:keys [genre description narrative name audience id url mtime ctime]} evidence
-                  text ()]
-              (conj r
-                    [:div.panel.panel-default
-                     [:div.panel-heading {:id (str "heading" id)
-                                          :role "tab"}
-                      [:div.panel-title
-                       [:a {:href "#" :on-click #(do (.preventDefault %)
-                                                   (init-evidence-form evidence state true)
-                                                   (swap! state assoc :tab [evidence-form data state init-data] :input_mode nil))}
-                        [:div.url [:div {:style {:float "left"}} [:i.fa.fa-link]]  url]]
-                       (when-not (every? #(blank? %) (vector genre description narrative name audience))
-                         [:div.show-more [:a {:role "button" :data-toggle "collapse"
-                                              :data-parent "#accordion"
-                                              :href (str "#collapse" id)
-                                              :aria-expanded "true"
-                                              :aria-controls (str "collapse" id)} (t :admin/Showmore)]])]
-                      [:div [:button {:type "button"
-                                      :aria-label "OK"
-                                      :class "close panel-close"
-                                      :on-click #(delete-evidence! id data state init-data)}
-                             [:span {:aria-hidden "true"
-                                     :dangerouslySetInnerHTML {:__html "×"}}]]]
-                      ]
-                     (when-not (every? #(blank? %) (vector genre description narrative name audience))
+  (let [evidence-name-atom (cursor state [:evidence :name])
+        evidence-description-atom (cursor state [:evidence :description])
+        new-input (cursor state [:new_input])]
+    (reduce (fn [r evidence]
+              (let [{:keys [description name id url mtime ctime evidence_type]} evidence
+                    index (inc (.indexOf (:evidences data) evidence))
+                    collapse-div-class (if (and (= index (count (:evidences data))) @new-input) "panel-collapse collapse in" "panel-collapse collapse")]
+                (init-evidence-form evidence state true)
+                (conj r
+                      [:div.panel.panel-default
+                       [:div.panel-heading {:id (str "heading" id)
+                                            :role "tab"}
+                        [:div.panel-title
+                         [:div.url [:div {:style {:float "left"}} [evidence-icon evidence_type] #_[:i.fa.fa-link]] (hyperlink url)]
+                         (when-not (blank? name) [:div.inline [:label (t :badge/Name) ": "] name])
+                         (when-not (blank? description) [:div [:label (t :admin/Description)]   description])]
+                        [:div [:button {:type "button"
+                                        :aria-label "OK"
+                                        :class "close panel-edit"
+                                        :on-click #(do (.preventDefault %)
+                                                     (init-evidence-form evidence state true))
+                                        :role "button" :data-toggle "collapse"
+                                        :data-parent "#accordion"
+                                        :href (str "#collapse" id)
+                                        :aria-expanded "true"
+                                        :aria-controls (str "collapse" id)}
+                               [:i.fa.fa-edit.edit-evidence]]];;edit-button
+
+                        [:div [:button {:type "button"
+                                        :aria-label "OK"
+                                        :class "close panel-close"
+                                        :on-click #(do (.preventDefault %)(delete-evidence! id data state init-data))}
+                               [:i.fa.fa-trash.trash]]]] ;;delete-button
+
                        [:div {:id (str "collapse" id)
-                              :class "panel-collapse collapse"
+                              :class collapse-div-class
                               :role "tabpanel"
                               :aria-labelledby (str "heading" id)}
                         [:div.panel-body.evidence-panel-body {:style {:padding-top "10px"}}
-                         (when-not (blank? name) [:div.inline [:label (t :badge/Name) ": "] name])
-                         (when-not (blank? description) [:div [:label (t :admin/Description)]  [:div.description description]])
-                         ]])])
-  )
-            )[:div {:id "accordion" :class "panel-group evidence-list" :role "tablist" :aria-multiselectable "true"}] (:evidences data)))
+                         [:div.form-group
+                          [:label.col-md-3 "Name"]
+                          [:div.col-md-9
+                           [input {:name "name" :atom evidence-name-atom :type "text"} nil]]]
+                         [:div.form-group
+                          [:label.col-md-3 (t :page/Description)]
+                          [:div.col-md-9
+                           [input {:name "Description" :rows 5 :cols 40 :atom evidence-description-atom } true]]]
+                         [:hr]
+                         [:div
+                          [:button {:type         "button"
+                                    :class        "btn btn-primary"
+                                    :on-click     #(do (.preventDefault %)(save-badge-evidence data state init-data))
+                                    :data-toggle "collapse"
+                                    :data-target (str "#collapse" id)}
+                           (t :badge/Save)]]
+                         ]]]))
+              )[:div {:id "accordion" :class "panel-group evidence-list" :role "tablist" :aria-multiselectable "true"}] (:evidences data))))

 (defn evidence-block [data state init-data]
   [:div#badge-settings
    [:div.form-group
-    [:label {:class "col-md-12 sub-heading" :for "evidence"} (t :badge/Evidence)]
-
-
     [:div.col-md-9 {:class "new-evidence"}
-     [:i.fa.fa-plus-square.fa-sm]
-     [:a {:href "#" :on-click #(do (.preventDefault %)
-                                 (swap! state assoc :evidence nil
-                                        :show_form nil
-                                        :input_mode nil)
-                                 (swap! state assoc :tab [evidence-form data state init-data] :tab-no 2))} (t :badge/Addnewevidence)]]]
-
-
-   [:div.form-group
-    [:div.col-md-9 [evidence-list data state init-data]]]
-   ])
+     [:i.fa.fa-plus]
+     [:a {:on-click #(do (.preventDefault %)
+                       (swap! state assoc :evidence nil
+                              :new_input true)
+                       (swap! state assoc :tab [evidence-form data state init-data] :tab-no 2))} (t :badge/Addnewevidence)]]]
+   (when-not (empty? (:evidences data)) [:div.form-group
+                                         [:div.col-md-12 [evidence-list data state init-data]]])])

 (defn evidence-modal [state]
   (fn []


don't show user emails in invite

don't show user emails in invite

--- src/chat/client/views/group_invite.cljs
+++ src/chat/client/views/group_invite.cljs
@@ -24,21 +24,8 @@
                                     (when on-focus (on-focus)))}
           "invite")
         (dom/div #js {:className "invite-form"}
-          (om/build input {:value invitee-email}
-                    {:opts {:type :autocomplete
-                            :edit-key [:value]
-                            :update-fn (fn [v]
-                                         (om/set-state! owner :invitee-email (str v)))
-                            :placeholder "User to invite"
-                            :search-fn
-                            (fn [s ch]
-                              ; TODO: don't show users already in group
-                              (let [emails (->> (store/get-user-emails)
-                                                (filter #(not= -1 (.indexOf % s)))
-                                                (cons s))]
-                                (put! ch emails)))
-                            :choice-render-fn str
-                            :class "autocomplete"}})
+          (dom/input #js {:value invitee-email :type "email" :placeholder "email address"
+                           :onChange (fn [e] (om/set-state! owner :invitee-email (.. e -target -value)))})
           (dom/button #js {:className "invite"
                            :disabled (string/blank? invitee-email)
                            :onClick


Fix a missing newline when using --color with the standalone REPL.
The original output was:

  user=> (/ 1 0)
  #<ArithmeticException java.lang.ArithmeticException: Divide by zero>user=>

print-err doesn't print a newline, so use (or print-err print) and print
a newline after it.

--- src/clj/reply/eval_modes/standalone.clj
+++ src/clj/reply/eval_modes/standalone.clj
@@ -34,7 +34,8 @@
                  (catch InterruptedException e nil)
                  (catch Throwable t
                    (let [e (clojure.main/repl-exception t)]
-                     ((or print-err println) e))
+                     ((or print-err print) e)
+                     (println))
                    failure-sentinel))]
     ;lazyseq: (1 2 3 4 5 ...)
     ;pr: "(1 2 3 4 5 ...)"


Focusing text input on update creates problems

--- src/cljs/cglossa/search_inputs/cwb.cljs
+++ src/cljs/cglossa/search_inputs/cwb.cljs
@@ -188,9 +188,6 @@
   [{:keys [search-view search-queries]} {:keys [corpus]}]
   (reagent/create-class
     {:component-did-mount
-     focus-text-input
-
-     :component-did-update
      focus-text-input

      :reagent-render


fixed not found layout rendering

fixed not found layout rendering

--- src/cljs/swarmpit/component/layout.cljs
+++ src/cljs/swarmpit/component/layout.cljs
@@ -50,7 +50,7 @@
   (keyword (first (str/split (name handler) #"-"))))

 (def single-pages
-  #{:login :error :unauthorized nil})
+  #{:login :error :unauthorized :not-found nil})

 (defn- page-layout?
   [handler]


added more destructuring functions - key, value - first-value-fn, second-value-fn - key-fn, value-fn

--- src/clojure/sparkling/destructuring.clj
+++ src/clojure/sparkling/destructuring.clj
@@ -1,7 +1,29 @@
 (ns sparkling.destructuring
   "Contains wrapper-functions to destructure scala/spark data structures"
+  (:refer-clojure :exclude [key])
   (:import [scala Tuple2 Tuple3]
            [com.google.common.base Optional]))
+
+
+(defn key [^Tuple2 tuple] (._1 tuple))
+(defn value [^Tuple2 tuple] (._2 tuple))
+
+(defn first-value-fn [f]
+  "Wraps a function f so that when the wrapped function is called on a tuple2, f is called with the second element from that tuple."
+  (fn [^Tuple2 tuple]
+    (f (._1 tuple))))
+
+(defn second-value-fn [f]
+  "Wraps a function f so that when the wrapped function is called on a tuple2, f is called with the second element from that tuple."
+  (fn [^Tuple2 tuple]
+    (f (._2 tuple))))
+
+
+(def key-fn first-value-fn)
+(def value-fn second-value-fn)
+
+
+

 (defn key-value-fn
   "wraps a function f [k v] to untuple a key/value tuple. Useful e.g. on map for PairRDD."


added sparkling.core to the required namespaces on the executors.

--- src/clojure/sparkling/serialization.clj
+++ src/clojure/sparkling/serialization.clj
@@ -1,6 +1,7 @@
 (ns sparkling.serialization
   (:require [clojure.tools.logging :as log]
             [carbonite.api :as carbonite]
+            [sparkling.core :as core]
             [sparkling.serializers :as serializer])
   (:import [com.twitter.chill Tuple2Serializer Tuple3Serializer]
            [org.objenesis.strategy StdInstantiatorStrategy]
@@ -117,6 +118,7 @@
 (defn register-base-classes [kryo]
   (require 'clojure.tools.logging)
   (require 'carbonite.api)
+  (require 'sparkling.core)
   (require 'sparkling.serializers)

   ;(log/info "Registering base classes for kryo")


Added ability for divergent entities to read forks in timeline, and fork new divergent entities

--- src/divergence/system/time_travel.cljs
+++ src/divergence/system/time_travel.cljs
@@ -61,13 +61,22 @@
                 future-state (get-in @timestream future-value-path)
                 n (:name @(@e/entity-atom->unique-entity-atom e))]]

-    ;; TODO we need to check if there is even a time event in the future
+    (timeviz/draw-time-node [(first future-node) (+ (second future-node) (timeviz/find-time-offset @timestream (first future-node)))])

     ;; If a time event exists in this future state, we'll reset! the entity to that value
     ;; Otherwise we'll write the current value of the entity into the timestream
-    (timeviz/draw-time-node [(first future-node) (+ (second future-node) (timeviz/find-time-offset @timestream (first future-node)))])
     (if future-state
-      (reset! e future-state)
+      ;; There is a future state, so let's check if there are forks too
+      (if-let [forks (get-in @timestream (conj future-node :forks))]
+        (do
+          (reset! e future-state)
+          (doseq [fork forks]
+            ;; The fork represents the timeline number of the fork
+            ;; All timelines start at 0 so we need to create a divergent
+            ;; entity at [fork-timeline 0]
+            (create-divergent-entity [fork 0])))
+        ;; There are no forks, so we can just update the current entity
+        (reset! e future-state))
       ;; Now check if the person is a player of not
       (if (= :player n)
         (do


using latest spec

using latest spec

--- test/celestial/integration/proxmox.clj
+++ test/celestial/integration/proxmox.clj
@@ -2,30 +2,27 @@
   "Integration tests assume a proxmox vm with local address make sure to configure it"
   (:use clojure.test
         proxmox.provider
-        [celestial.common :only (config)]
+        [celestial.common :only (config slurp-edn)]
         )
   (:import
     [proxmox.provider Container]))

-(def spec
-  {:vmid 203 :ostemplate  "local:vztmpl/ubuntu-12.04-puppet_3-x86_64.tar.gz"
-   :cpus  4 :memory  4096 :hostname  "foobar" :disk 30
-   :ip_address  "192.168.1.30" :password "foobar1" :hypervisor "proxmox"})
+(def spec (slurp-edn "fixtures/redis-system.edn"))

 (def local-prox
-  {:hypervisor  {:username "root" :password "foobar" :host "localhost" :ssh-port 22222}})
+  {:hypervisor {:username "root" :password "foobar" :host "localhost" :ssh-port 22222}})

-(def fake-id (assoc spec :vmid 190))
+(def fake-id (update-in spec [:machine :vmid] (fn [o] 190)))

 (alter-var-root (var config) (fn [old] local-prox))

 (deftest ^:proxmox non-existing
-  (let [{:keys [hypervisor]} fake-id  ct (Container. hypervisor fake-id)]
+  (let [{:keys [machine]} fake-id  ct (Container. (machine :hypervisor) machine)]
     (.stop ct)
     (.delete ct)))

 (deftest ^:proxmox full-cycle
-  (let [{:keys [hypervisor]} spec  ct (Container. hypervisor spec)]
+  (let [{:keys [machine]} spec ct (Container. (machine :hypervisor) machine)]
     (.stop ct)
     (.delete ct)
     (.create ct)


Update tests to use components.

Update tests to use components.

--- test/clj/hatnik/worker/worker_test.clj
+++ test/clj/hatnik/worker/worker_test.clj
@@ -2,51 +2,62 @@
   (:require [clojure.test :refer :all]
             [hatnik.worker.worker :refer :all]
             [hatnik.db.storage :as stg]
-            [hatnik.db.memory-storage :refer [create-memory-storage]]
-            [hatnik.versions :as ver]))
+            [hatnik.db.memory-storage :refer [map->MemoryStorage]]
+            [hatnik.versions :as ver]
+            [com.stuartsierra.component :as component]))

-(defn prepare-db-fixture [f]
-  (reset! stg/storage (create-memory-storage))
-  (let [user-id (stg/create-user! @stg/storage "me@email.com")
-        project-id (stg/create-project! @stg/storage {:name "Default"
-                                                      :user-id user-id})]
-    (stg/create-action! @stg/storage user-id {:project-id project-id
+(defn get-db []
+  (let [db (component/start (map->MemoryStorage {}))
+        user-id (stg/create-user! db "me@email.com" "token")
+        project-id (stg/create-project! db {:name "Default"
+                                            :user-id user-id})]
+    (stg/create-action! db user-id {:project-id project-id
                                               :type "email"
                                               :library "foo-library"
                                               :last-processed-version "1.0.0"})
-    (stg/create-action! @stg/storage user-id {:project-id project-id
+    (stg/create-action! db user-id {:project-id project-id
                                               :type "email"
                                               :library "foo-library"
-                                              :last-processed-version "0.9.0"}))
-  (f))
-
-(use-fixtures :each prepare-db-fixture)
+                                              :last-processed-version "0.9.0"})
+    db))

 (deftest test-check-library-and-perform-actions-correct
-  (with-redefs [ver/latest-release (constantly "2.0.0")]
-    (check-library-and-perform-actions "foo-library" (stg/get-actions @stg/storage)))
-  (doseq [action (stg/get-actions @stg/storage)]
-    (is (= (:last-processed-version action) "2.0.0"))))
+  (let [db (get-db)]
+   (with-redefs [ver/latest-release (constantly "2.0.0")]
+     (check-library-and-perform-actions "foo-library" (stg/get-actions db)
+                                        db perform-action-disabled {}))
+   (doseq [action (stg/get-actions db)]
+     (is (= (:last-processed-version action) "2.0.0")))
+
+   (component/stop db)))

 (deftest test-check-library-and-perform-actions-new-version-is-smaller
-  (let [actions (stg/get-actions @stg/storage)
+  (let [db (get-db)
+        actions (stg/get-actions db)
         actions-by-id (into {}
                             (map #(vector (:id %) %) actions))]
     (with-redefs [ver/latest-release (constantly "0.5.0")]
-      (check-library-and-perform-actions "foo-library" actions))
-    (doseq [action (stg/get-actions @stg/storage)]
+      (check-library-and-perform-actions "foo-library" actions
+                                         db perform-action-disabled {}))
+    (doseq [action (stg/get-actions db)]
       (is (= (:last-processed-version action)
-             (:last-processed-version (actions-by-id (:id action))))))))
+             (:last-processed-version (actions-by-id (:id action))))))
+
+    (component/stop db)))

 (deftest test-check-library-and-perform-actions-new-version-is-null
-  (let [actions (stg/get-actions @stg/storage)
+  (let [db (get-db)
+        actions (stg/get-actions db)
         actions-by-id (into {}
                             (map #(vector (:id %) %) actions))]
     (with-redefs [ver/latest-release (constantly nil)]
-      (check-library-and-perform-actions "foo-library" actions))
-    (doseq [action (stg/get-actions @stg/storage)]
+      (check-library-and-perform-actions "foo-library" actions
+                                         db perform-action-disabled {}))
+    (doseq [action (stg/get-actions db)]
       (is (= (:last-processed-version action)
-             (:last-processed-version (actions-by-id (:id action))))))))
+             (:last-processed-version (actions-by-id (:id action))))))
+
+    (component/stop db)))


Added missing tests

Added missing tests

--- test/emender_jenkins/rest_api_test.clj
+++ test/emender_jenkins/rest_api_test.clj
@@ -114,3 +114,86 @@
         (is (callable? 'emender-jenkins.rest-api/job-already-exist-response))))

+(deftest test-start-job-existence
+    "Check that the emender-jenkins.rest-api/start-job definition exists."
+    (testing "if the emender-jenkins.rest-api/start-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/start-job))))
+
+
+(deftest test-enable-job-existence
+    "Check that the emender-jenkins.rest-api/enable-job definition exists."
+    (testing "if the emender-jenkins.rest-api/enable-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/enable-job))))
+
+
+(deftest test-disable-job-existence
+    "Check that the emender-jenkins.rest-api/disable-job definition exists."
+    (testing "if the emender-jenkins.rest-api/disable-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/disable-job))))
+
+
+(deftest test-delete-job-existence
+    "Check that the emender-jenkins.rest-api/delete-job definition exists."
+    (testing "if the emender-jenkins.rest-api/delete-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/delete-job))))
+
+
+(deftest test-create-job-existence
+    "Check that the emender-jenkins.rest-api/create-job definition exists."
+    (testing "if the emender-jenkins.rest-api/create-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/create-job))))
+
+
+(deftest test-uri->job-name-existence
+    "Check that the emender-jenkins.rest-api/uri->job-name definition exists."
+    (testing "if the emender-jenkins.rest-api/uri->job-name definition exists."
+        (is (callable? 'emender-jenkins.rest-api/uri->job-name))))
+
+
+(deftest test-get-job-existence
+    "Check that the emender-jenkins.rest-api/get-job definition exists."
+    (testing "if the emender-jenkins.rest-api/get-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/get-job))))
+
+
+(deftest test-update-job-existence
+    "Check that the emender-jenkins.rest-api/update-job definition exists."
+    (testing "if the emender-jenkins.rest-api/update-job definition exists."
+        (is (callable? 'emender-jenkins.rest-api/update-job))))
+
+
+(deftest test-get-jobs-existence
+    "Check that the emender-jenkins.rest-api/get-jobs definition exists."
+    (testing "if the emender-jenkins.rest-api/get-jobs definition exists."
+        (is (callable? 'emender-jenkins.rest-api/get-jobs))))
+
+
+(deftest test-get-job-results-existence
+    "Check that the emender-jenkins.rest-api/get-job-results definition exists."
+    (testing "if the emender-jenkins.rest-api/get-job-results definition exists."
+        (is (callable? 'emender-jenkins.rest-api/get-job-results))))
+
+
+(deftest test-job-started-handler-existence
+    "Check that the emender-jenkins.rest-api/job-started-handler definition exists."
+    (testing "if the emender-jenkins.rest-api/job-started-handler definition exists."
+        (is (callable? 'emender-jenkins.rest-api/job-started-handler))))
+
+
+(deftest test-job-finished-handler-existence
+    "Check that the emender-jenkins.rest-api/job-finished-handler definition exists."
+    (testing "if the emender-jenkins.rest-api/job-finished-handler definition exists."
+        (is (callable? 'emender-jenkins.rest-api/job-finished-handler))))
+
+
+(deftest test-job-results-existence
+    "Check that the emender-jenkins.rest-api/job-results definition exists."
+    (testing "if the emender-jenkins.rest-api/job-results definition exists."
+        (is (callable? 'emender-jenkins.rest-api/job-results))))
+
+
+(deftest test-unknown-call-handler-existence
+    "Check that the emender-jenkins.rest-api/unknown-call-handler definition exists."
+    (testing "if the emender-jenkins.rest-api/unknown-call-handler definition exists."
+        (is (callable? 'emender-jenkins.rest-api/unknown-call-handler))))
+


Exception catching test for read-building-jobs-from-jenkins

--- test/emender_jenkins/rest_api_test.clj
+++ test/emender_jenkins/rest_api_test.clj
@@ -680,3 +680,8 @@
                   "userRemoteConfigs"
                   [{"url" "git@git.domain.name:example-documentation/guide.git"}]}}]))))

+(deftest test-read-building-jobs-from-jenkins-exception-catching
+    "Check the function emender-jenkins.rest-api/read-building-jobs-from-jenkins."
+    (with-redefs [jenkins-api/read-list-of-all-jobs (fn [url job-list-part] (throw (new Exception "Exception!")))]
+        (is (= (read-building-jobs-from-jenkins "url" "job-list-part") nil))))
+


add insert tests

add insert tests


Use release instead of prod

Use release instead of prod

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -124,7 +124,7 @@
              :main         {{ns-name}}.server
              :aot          [{{ns-name}}.server]
              :uberjar-name "{{name}}.jar"
-             :prep-tasks   ["compile" ["prod"]{{{prep-garden}}}{{{prep-less}}}]}{{/handler?}}}
+             :prep-tasks   ["compile" ["release"]{{{prep-garden}}}{{{prep-less}}}]}{{/handler?}}}

   :prep-tasks [{{#garden?}}["garden" "once"]{{/garden?}}{{#less?}}
                ["less" "once"]{{/less?}}])


Shorter second hand.

Shorter second hand.

--- ui/src/ui/core.cljs
+++ ui/src/ui/core.cljs
@@ -40,7 +40,7 @@
           (transact! data :elapsed-seconds #(mod interval-seconds 60))
           (transact! data :elapsed-minutes #(mod (/ interval-seconds 60) 60))
           (transact! data :elapsed-hours #(mod (/ interval-seconds 60 60) 24))
-          (<! (timeout 30))
+          (<! (timeout 10))
           (recur))))
     IRenderState
     (render-state [_ _]
@@ -61,20 +61,19 @@
                           :cx x
                           :cy y
                           :fill "white"})
-             (when-not (= 0 elapsed-minutes)
-               (pie x y r "#d9d9d9" (* 6 10 elapsed-minutes)))
-             (pie x y (/ r 1.5) "#cccccc" (* 30 10 elapsed-hours))
-             (line #js {:x1 x
-                        :y1 y
+             (pie x y r "#d9d9d9" (* 6 10 elapsed-minutes))
+             (pie x y (/ r 1.4) "#cccccc" (* 30 10 elapsed-hours))
+             (line #js {:x1 (+ x (angleDx (* 6 elapsed-seconds) (/ r 1.4)))
+                        :y1 (+ y (angleDy (* 6 elapsed-seconds) (/ r 1.4)))
                         :x2 (+ x (angleDx (* 6 elapsed-seconds) r))
                         :y2 (+ y (angleDy (* 6 elapsed-seconds) r))
-                        :style #js {:stroke "#737373"
-                                    :stroke-width "1px"}
+                        :style #js {:stroke "#bfbfbf"
+                                    :strokeWidth "4px"}
                         :transform (str "rotate(-90," x "," y")")})
              (text #js {:x "190"
                         :y "280"
                         :fill "blue"
-                        :style #js {:font-size "90px"}}
+                        :style #js {:fontSize "90px"}}
                    (if (= 0 (int elapsed-hours))
                      (str (int elapsed-minutes) "m")
                      (str (int elapsed-hours) "h " (int elapsed-minutes) "m")))


Use integers instead of characters, refs DJSON-1

* Eliminates reflection warnings in Clojure 1.3.0
* Much faster

--- src/main/clojure/clojure/data/json.clj
+++ src/main/clojure/clojure/data/json.clj
@@ -23,6 +23,9 @@

 ;;; JSON READER

+(defmacro ^{:private true} codepoint [c]
+  (int c))
+
 (declare read-json-reader)

 (defn- read-json-array [^PushbackReader stream keywordize?]
@@ -30,12 +33,12 @@
   ;; opening bracket.
   (loop [i (.read stream), result (transient [])]
     (when (neg? i) (throw (EOFException. "JSON error (end-of-file inside array)")))
-    (let [c (char i)]
+    (let [c i]
       (cond
        (Character/isWhitespace c) (recur (.read stream) result)
-       (= c \,) (recur (.read stream) result)
-       (= c \]) (persistent! result)
-       :else (do (.unread stream (int c))
+       (= c (codepoint \,)) (recur (.read stream) result)
+       (= c (codepoint \])) (persistent! result)
+       :else (do (.unread stream i)
                  (let [element (read-json-reader stream keywordize? true nil)]
                    (recur (.read stream) (conj! result element))))))))

@@ -44,15 +47,15 @@
   ;; opening bracket.
   (loop [i (.read stream), key nil, result (transient {})]
     (when (neg? i) (throw (EOFException. "JSON error (end-of-file inside array)")))
-    (let [c (char i)]
+    (let [c i]
       (cond
        (Character/isWhitespace c) (recur (.read stream) key result)

-       (= c \,) (recur (.read stream) nil result)
-
-       (= c \:) (recur (.read stream) key result)
-
-       (= c \}) (if (nil? key)
+       (= c (codepoint \,)) (recur (.read stream) nil result)
+
+       (= c (codepoint \:)) (recur (.read stream) key result)
+
+       (= c (codepoint \})) (if (nil? key)
                   (persistent! result)
                   (throw (Exception. "JSON error (key missing value in object)")))

@@ -84,15 +87,15 @@
 (defn- read-json-escaped-character [^PushbackReader stream]
   ;; Expects to be called with the head of the stream AFTER the
   ;; initial backslash.
-  (let [c (char (.read stream))]
+  (let [c (.read stream)]
     (cond
-     (#{\" \\ \/} c) c
-     (= c \b) \backspace
-     (= c \f) \formfeed
-     (= c \n) \newline
-     (= c \r) \return
-     (= c \t) \tab
-     (= c \u) (read-json-hex-character stream))))
+     (#{(codepoint \") (codepoint \\) (codepoint \/)} c) (char c)
+     (= c (codepoint \b)) \backspace
+     (= c (codepoint \f)) \formfeed
+     (= c (codepoint \n)) \newline
+     (= c (codepoint \r)) \return
+     (= c (codepoint \t)) \tab
+     (= c (codepoint \u)) (read-json-hex-character stream))))

 (defn- read-json-quoted-string [^PushbackReader stream]
   ;; Expects to be called with the head of the stream AFTER the
@@ -100,12 +103,12 @@
   (let [buffer (StringBuilder.)]
     (loop [i (.read stream)]
       (when (neg? i) (throw (EOFException. "JSON error (end-of-file inside array)")))
-      (let [c (char i)]
+      (let [c i]
         (cond
-         (= c \") (str buffer)
-         (= c \\) (do (.append buffer (read-json-escaped-character stream))
+         (= c (codepoint \")) (str buffer)
+         (= c (codepoint \\)) (do (.append buffer (read-json-escaped-character stream))
                       (recur (.read stream)))
-         :else (do (.append buffer c)
+         :else (do (.append buffer (char c))
                    (recur (.read stream))))))))

 (defn- read-json-reader
@@ -115,51 +118,51 @@
 	 (if eof-error?
 	   (throw (EOFException. "JSON error (end-of-file)"))
 	   eof-value)
-	 (let [c (char i)]
+	 (let [c i]
 	   (cond
 	    ;; Ignore whitespace
 	    (Character/isWhitespace c) (recur (.read stream))

 	    ;; Read numbers, true, and false with Clojure reader
-	    (#{\- \0 \1 \2 \3 \4 \5 \6 \7 \8 \9} c)
+	    (#{(codepoint \-) (codepoint \0) (codepoint \1) (codepoint \2) (codepoint \3) (codepoint \4) (codepoint \5) (codepoint \6) (codepoint \7) (codepoint \8) (codepoint \9)} c)
 	    (do (.unread stream i)
 		(read stream true nil))

 	    ;; Read strings
-	    (= c \") (read-json-quoted-string stream)
+	    (= c (codepoint \")) (read-json-quoted-string stream)

 	    ;; Read null as nil
-	    (= c \n) (let [ull [(char (.read stream))
-				(char (.read stream))
-				(char (.read stream))]]
+	    (= c (codepoint \n)) (let [ull [(char (.read stream))
+                                  (char (.read stream))
+                                  (char (.read stream))]]
 		       (if (= ull [\u \l \l])
 			 nil
 			 (throw (Exception. (str "JSON error (expected null): " c ull)))))

 	    ;; Read true
-	    (= c \t) (let [rue [(char (.read stream))
-				(char (.read stream))
-				(char (.read stream))]]
-		       (if (= rue [\r \u \e])
+	    (= c (codepoint \t)) (let [rue [(.read stream)
+                                            (.read stream)
+                                            (.read stream)]]
+		       (if (= rue [(codepoint \r) (codepoint \u) (codepoint \e)])
 			 true
 			 (throw (Exception. (str "JSON error (expected true): " c rue)))))

 	    ;; Read false
-	    (= c \f) (let [alse [(char (.read stream))
-				 (char (.read stream))
-				 (char (.read stream))
-				 (char (.read stream))]]
-		       (if (= alse [\a \l \s \e])
+	    (= c (codepoint \f)) (let [alse [(.read stream)
+                                             (.read stream)
+                                             (.read stream)
+                                             (.read stream)]]
+		       (if (= alse [(codepoint \a) (codepoint \l) (codepoint \s) (codepoint \e)])
 			 false
 			 (throw (Exception. (str "JSON error (expected false): " c alse)))))

 	    ;; Read JSON objects
-	    (= c \{) (read-json-object stream keywordize?)
+	    (= c (codepoint \{)) (read-json-object stream keywordize?)

 	    ;; Read JSON arrays
-	    (= c \[) (read-json-array stream keywordize?)
-
-	    :else (throw (Exception. (str "JSON error (unexpected character): " c)))))))))
+	    (= c (codepoint \[)) (read-json-array stream keywordize?)
+
+	    :else (throw (Exception. (str "JSON error (unexpected character): " (char c))))))))))

 (defprotocol Read-JSON-From
   (read-json-from [input keywordize? eof-error? eof-value]


Omit clojure.core from get-tests

Omit clojure.core from get-tests

To avoid infinite recursion on *ns* and *1,*2,*3

--- src/main/clojure/lazytest/testable.clj
+++ src/main/clojure/lazytest/testable.clj
@@ -19,10 +19,11 @@
 (extend-protocol Testable
   clojure.lang.Namespace
   (get-tests [this-ns]
-    (if-let [f (:get-tests (meta this-ns))]
-      (do (assert (fn? f)) (f))
-      (filter-focused
-       (mapcat get-tests (vals (ns-interns this-ns))))))
+    (when-not (= (the-ns 'clojure.core) this-ns)
+      (if-let [f (:get-tests (meta this-ns))]
+	(do (assert (fn? f)) (f))
+	(filter-focused
+	 (mapcat get-tests (vals (ns-interns this-ns)))))))

   clojure.lang.Var
   (get-tests [this-var]


formation changes

formation changes

--- test/papaline/core_test.clj
+++ test/papaline/core_test.clj
@@ -102,7 +102,7 @@
 (deftest test-error-handler-with-name
   (let [stage-name "demo-stage-0"
         f (named-stage stage-name (fn [] (throw (ex-info "expected error" {}))))
-        p (pipeline [f] :error-handler (fn [e]
-                                   (let [data (ex-data e)]
-                                     (is (= stage-name (:stage data))))))]
+        p (pipeline [f] :error-handler
+                    (fn [e]
+                      (is (= stage-name (:stage (ex-data e))))))]
     (try (run-pipeline-wait p) (catch Exception e))))


Add a regression test for the client sending the request body after a 100 continue was requested and denied.

--- test/picard/test/server.clj
+++ test/picard/test/server.clj
@@ -598,20 +598,35 @@
   (deftrackedapp [downstream]
     (fn [evt val]
       (when (= :request evt)
-        (downstream :response [417 {"content-length" "0"}]))))
+        (let [[{request-method :request-method}] val]
+          (if (= "GET" request-method)
+            (downstream :response [200 {"content-length" "5"} "Hello"])
+            (downstream :response [417 {"content-length" "0"} ""]))))))

   (http-write "POST / HTTP/1.1\r\n"
               "Content-Length: 5\r\n"
-              "Connection: close\r\n"
               "Expect: 100-continue\r\n\r\n")

   (is (next-msgs
        :request [(includes-hdrs {"expect" "100-continue"}) :chunked]
        :done    nil))

-  (is (received-response
+  (is (receiving
        "HTTP/1.1 417 Expectation Failed\r\n"
        "content-length: 0\r\n\r\n"))
+
+  (http-write "Hello"
+              "GET / HTTP/1.1\r\n"
+              "Connection: close\r\n\r\n")
+
+  (is (next-msgs
+       :request [(includes-hdrs {:request-method "GET"}) nil]
+       :done    nil))
+
+  (is (received-response
+       "HTTP/1.1 200 OK\r\n"
+       "content-length: 5\r\n\r\n"
+       "Hello"))

   (is (not-receiving-messages)))


+refer writer/reload

+refer writer/reload

--- test/babel/test/fr.clj
+++ test/babel/test/fr.clj
@@ -7,6 +7,7 @@
             [babel.francais.morphology :refer [fo]]
             [babel.francais.writer :refer [expression]]
             [babel.over :as over]
+            [babel.writer :refer [reload]]
             [babel.workbook.fr :refer [over rules]]
             [clojure.string :as string]
             [clojure.test :refer :all]


extend the auto-scroll triggering range a bit

--- src-cljs/frontend/components/chat.cljs
+++ src-cljs/frontend/components/chat.cljs
@@ -150,7 +150,8 @@
     (will-update [_ next-props next-state]
       ;; check for scrolled all of the way down
       (let [node (om/get-node owner "chat-messages")
-            auto-scroll? (<= (- (.-scrollHeight node) (.-scrollTop node))
+            em 16 ;; extra padding for the scroll
+            auto-scroll? (<= (- (.-scrollHeight node) (.-scrollTop node) em)
                              (.-clientHeight node))]
         (when (not= (om/get-state owner :auto-scroll?) auto-scroll?)
           (om/set-state! owner :auto-scroll? auto-scroll?))))


fix plan payment display name

fix plan payment display name

--- src-cljs/frontend/components/plan.cljs
+++ src-cljs/frontend/components/plan.cljs
@@ -192,7 +192,7 @@

 (defn payment [{:keys [plan team-uuid doc-id] :as data} owner]
   (reify
-    om/IDisplayName (display-name "Plan payment")
+    om/IDisplayName (display-name [_] "Plan payment")
     om/IRender
     (render [_]
       (let [{:keys [cast! team-db]} (om/get-shared owner)]


Modified type 20 configuration  * implement offsets as array type

--- src/ais/mapping/type_20.clj
+++ src/ais/mapping/type_20.clj
@@ -1,33 +1,28 @@
 (ns ais.mapping.type_20
   (:require [clojure.string :as string])
-  (:require [ais.vocab :as ais-vocab])
   (:require [ais.types :as ais-types])
-  (:require [ais.util :as ais-util])
-  (:require [ais.extractors :as ais-ex])
   (:require [ais.mapping.common :as ais-map-comm])
   (:gen-class))

+(def offset-seq-fields (list
+  {:len  12 :desc "Offset"         :tag "offset"     :fn ais-types/u}
+  {:len   4 :desc "Reserved slots" :tag "number"     :fn ais-types/u}
+  {:len   3 :desc "Time-out"       :tag "timeout"    :fn ais-types/u}
+  {:len  11 :desc "Increment"      :tag "increment"  :fn ais-types/u}
+))
+
+(defn field-mapper [_]
+  offset-seq-fields)
+
+(def bits-len (partial ais-types/array-bit-len 4 30))
+
+(def seq-handler (partial ais-types/a 30 field-mapper ais-map-comm/parse-binary))

 (def mapping-20 (list
-  {:len   6 :desc "Message Type"      :tag "type"         :fn (partial ais-map-comm/const 20)}
-  {:len   2 :desc "Repeat Indicator"  :tag "repeat"       :fn ais-types/u}
-  {:len  30 :desc "MMSI"              :tag "mmsi"         :fn ais-types/u}
-  {:len   2 :desc "Spare"             :tag "spare"        :fn ais-types/x}
-  {:len  12 :desc "Offset number 1"   :tag "offset1"      :fn ais-types/u}
-  {:len   4 :desc "Reserved slots"    :tag "number1"      :fn ais-types/u}
-  {:len   3 :desc "Time-out"          :tag "timeout1"     :fn ais-types/u}
-  {:len  11 :desc "Increment"         :tag "increment1"   :fn ais-types/u}
-  {:len  12 :desc "Offset number 2"   :tag "offset2"      :fn ais-types/u}
-  {:len   4 :desc "Reserved slots"    :tag "number2"      :fn ais-types/u}
-  {:len   3 :desc "Time-out"          :tag "timeout2"     :fn ais-types/u}
-  {:len  11 :desc "Increment"         :tag "increment2"   :fn ais-types/u}
-  {:len  12 :desc "Offset number 3"   :tag "offset3"      :fn ais-types/u}
-  {:len   4 :desc "Reserved slots"    :tag "number3"      :fn ais-types/u}
-  {:len   3 :desc "Time-out"          :tag "timeout3"     :fn ais-types/u}
-  {:len  11 :desc "Increment"         :tag "increment3"   :fn ais-types/u}
-  {:len  12 :desc "Offset number 4"   :tag "offset4"      :fn ais-types/u}
-  {:len   4 :desc "Reserved slots"    :tag "number4"      :fn ais-types/u}
-  {:len   3 :desc "Time-out"          :tag "timeout4"     :fn ais-types/u}
-  {:len  11 :desc "Increment"         :tag "increment4"   :fn ais-types/u}
+  {:len   6 :desc "Message Type"      :tag "type"    :fn (partial ais-map-comm/const 20)}
+  {:len   2 :desc "Repeat Indicator"  :tag "repeat"  :fn ais-types/u}
+  {:len  30 :desc "MMSI"              :tag "mmsi"    :fn ais-types/u}
+  {:len   2 :desc "Spare"             :tag "spare"   :fn ais-types/x}
+  {:len bits-len :desc "Offsets"      :tag "offsets" :fn seq-handler :a true}
 ))


Removed dead code

Removed dead code

--- go-fighweel/src/cloj/lwjgl/resources.clj
+++ go-fighweel/src/cloj/lwjgl/resources.clj
@@ -18,19 +18,15 @@
   )

 ;; =============================================================================
-(defn put-close! [ch v]
-  (do
-    (async/put! ch v)
-    (async/close! ch)))
-
+; (defn put-close! [ch v]
+;   (do
+;     (async/put! ch v)
+;     (async/close! ch)))

 ;; =============================================================================
 ;; Async loading
 (defn mk-resource-manager [loader]
-  (let [store (atom {})
-        load-async! (fn [fname] (loader-p/load-async! loader fname))
-        load-blocking! (fn [fname] (loader-p/load-blocking! loader fname)) ]
-
+  (let [store (atom {}) ]
     (reify
       res-p/IResourceManagerInfo
       (find-img [_ id]           (println "not implemented"))
@@ -45,6 +41,15 @@

       (load-img! [this id file-name]
         (go
+          (comment
+            "Async loads img file but converts to OGL texture
+             non async (uses memoize) to prevent errors with
+             creating a gl texture on a thread not bound to an
+             opengl context.
+
+             Should be fine but if stuttery I can fiddle around
+             with lwjgl to get a context for the loader thread")
+
           (try
             (let [buffered-image (load-image file-name)
                   get-gl-texture (memoize make-texture-low)


Add messages to checks

Add messages to checks

--- test/io/perun_test.clj
+++ test/io/perun_test.clj
@@ -79,25 +79,55 @@
         (add-image :path "test-image.jpeg" :type "JPG" :width 54 :height 180)
         (add-image :path "test-image.png"  :type "PNG" :width 76 :height 37)
         (p/images-dimensions)
-        (value-check :path "test-image.jpg"  :value-fn #(meta= %1 %2 :width 10))
-        (value-check :path "test-image.jpg"  :value-fn #(meta= %1 %2 :height 10))
-        (value-check :path "test-image.jpg"  :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-dimensions))
-        (value-check :path "test-image.jpeg" :value-fn #(meta= %1 %2 :width 54))
-        (value-check :path "test-image.jpeg" :value-fn #(meta= %1 %2 :height 180))
-        (value-check :path "test-image.jpeg" :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-dimensions))
-        (value-check :path "test-image.png"  :value-fn #(meta= %1 %2 :width 76))
-        (value-check :path "test-image.png"  :value-fn #(meta= %1 %2 :height 37))
-        (value-check :path "test-image.png"  :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-dimensions))))
+        (value-check :path "test-image.jpg"
+                     :value-fn #(meta= %1 %2 :width 10)
+                     :msg "`images-dimensions should set `:width` metadata on image file")
+        (value-check :path "test-image.jpg"
+                     :value-fn #(meta= %1 %2 :height 10)
+                     :msg "`images-dimensions should set `:height` metadata on image file")
+        (value-check :path "test-image.jpg"
+                     :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-dimensions)
+                     :msg "`images-dimensions should add `:io.perun/images-dimensions` to `:io.perun/trace`")
+        (value-check :path "test-image.jpeg"
+                     :value-fn #(meta= %1 %2 :width 54)
+                     :msg "`images-dimensions should set `:width` metadata on image file")
+        (value-check :path "test-image.jpeg"
+                     :value-fn #(meta= %1 %2 :height 180)
+                     :msg "`images-dimensions should set `:height` metadata on image file")
+        (value-check :path "test-image.jpeg"
+                     :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-dimensions)
+                     :msg "`images-dimensions should add `:io.perun/images-dimensions` to `:io.perun/trace`")
+        (value-check :path "test-image.png"
+                     :value-fn #(meta= %1 %2 :width 76)
+                     :msg "`images-dimensions should set `:width` metadata on image file")
+        (value-check :path "test-image.png"
+                     :value-fn #(meta= %1 %2 :height 37)
+                     :msg "`images-dimensions should set `:height` metadata on image file")
+        (value-check :path "test-image.png"
+                     :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-dimensions)
+                     :msg "`images-dimensions should add `:io.perun/images-dimensions` to `:io.perun/trace`")))

 (deftesttask images-resize-test []
   (comp (add-image :path "test-image.jpg" :type "JPG" :width 10 :height 10)
         (p/images-resize :resolutions #{100 200})
-        (value-check :path "public/test-image_100.jpg" :value-fn #(meta= %1 %2 :width 100))
-        (value-check :path "public/test-image_100.jpg" :value-fn #(meta= %1 %2 :height 100))
-        (value-check :path "public/test-image_100.jpg" :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-resize))
-        (value-check :path "public/test-image_200.jpg" :value-fn #(meta= %1 %2 :width 200))
-        (value-check :path "public/test-image_200.jpg" :value-fn #(meta= %1 %2 :height 200))
-        (value-check :path "public/test-image_200.jpg" :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-resize))))
+        (value-check :path "public/test-image_100.jpg"
+                     :value-fn #(meta= %1 %2 :width 100)
+                     :msg "`images-resize resize image file and set `:width` metadata")
+        (value-check :path "public/test-image_100.jpg"
+                     :value-fn #(meta= %1 %2 :height 100)
+                     :msg "`images-resize resize image file and set `:height` metadata")
+        (value-check :path "public/test-image_100.jpg"
+                     :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-resize)
+                     :msg "`images-resize should add `:io.perun/images-resize` to `:io.perun/trace`")
+        (value-check :path "public/test-image_200.jpg"
+                     :value-fn #(meta= %1 %2 :width 200)
+                     :msg "`images-resize resize image file and set `:width` metadata")
+        (value-check :path "public/test-image_200.jpg"
+                     :value-fn #(meta= %1 %2 :height 200)
+                     :msg "`images-resize resize image file and set `:height` metadata")
+        (value-check :path "public/test-image_200.jpg"
+                     :value-fn #(meta-contains? %1 %2 :io.perun/trace :io.perun/images-resize)
+                     :msg "`images-resize should add `:io.perun/images-resize` to `:io.perun/trace`")))

 (deftask add-txt-file
   [p path    PATH  str "path of the file to add"


Add warn-on-reflection

Add warn-on-reflection

--- project.clj
+++ project.clj
@@ -4,4 +4,5 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.5.1"]
-                 [joda-time "2.2"]])
+                 [joda-time "2.2"]]
+  :warn-on-reflection true)


release 2.0.0

release 2.0.0

--- project.clj
+++ project.clj
@@ -6,7 +6,7 @@
 ;; babel.http: workbook, compojure http routes, querying from GETs, updating from POSTs, PUTs and PATCHes. all the ring/* and servlet-api :dependencies go here.
 ;; babel.<2 letter language code> babel.es, babel.en, etc.
 ;;
-(defproject babel "2.0.0-SNAPSHOT"
+(defproject babel "2.0.0"
   :description "A library for generation and parsing of expressions from grammars and lexicons."
   :url "http://github.com/ekoontz/babel"
   :license {:name "Proprietary: all rights reserved. No distribution allowed without consent of owners."}


Bump clojure.spec.alpha version

Bump clojure.spec.alpha version

Ran across a bug in initial implementation

--- project.clj
+++ project.clj
@@ -5,7 +5,7 @@
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[aleph "0.4.1"]
                  [org.clojure/clojure "1.9.0-alpha16"]
-                 [org.clojure/spec.alpha "0.1.94"]]
+                 [org.clojure/spec.alpha "0.1.108"]]
   :java-source-paths ["src/java"]
   ;; Pretty sure this was only ever involved for the sake of jzmq.
   ;; TODO: Verify that and then hopefully make it go away


Upgrade to clj-utils 6.0.1

Upgrade to clj-utils 6.0.1

--- project.clj
+++ project.clj
@@ -8,7 +8,7 @@
             :url "http://www.gnu.org/licenses/agpl-3.0.html"}
   :dependencies [
                  [cider-ci/clj-auth "5.0.1"]
-                 [cider-ci/clj-utils "6.0.0"]
+                 [cider-ci/clj-utils "6.0.1"]

                  ;[logbug "2.0.0-beta.10"]
                  [drtom/honeysql "1.3.0-beta.4"]


Problem with unsatisfied link error came from needing the reference to jzmq (or jeromq...whichever strikes your fancy)

--- project.clj
+++ project.clj
@@ -4,9 +4,9 @@
   :license {:name "Affero General Public License"
             :url "http://www.gnu.org/licenses/agpl.html"}
   :dependencies [[org.clojure/clojure "1.5.1"]
-                 ;;[cc.qbits/jilch "0.3.0"]
-                 ;;[org.zeromq/jzmq "2.2.0"]
+                 [org.zeromq/jzmq "2.2.1"]
                  [org.zeromq/cljzmq "0.1.1"]]
+  ;;:jvm-opts ["-Djava.library.path=/usr/lib:/usr/local/lib"]
   :profiles {:dev {:source-paths ["dev"]
                    :dependencies [[org.clojure/tools.namespace "0.2.3"]
                                   [org.clojure/java.classpath "0.2.0"]


Prepare for next release cycle.

Prepare for next release cycle.

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject onyx-app/lein-template "0.8.11.7"
+(defproject onyx-app/lein-template "0.8.11.8-SNAPSHOT"
   :description "Onyx Leiningen application template"
   :url "https://github.com/onyx-platform/onyx-template"
   :license {:name "Eclipse Public License"


Small fix

Small fix

--- project.clj
+++ project.clj
@@ -116,7 +116,7 @@
                        :aot            :all}}

-  :scss  {:buildsfc5407a8a019d52ac94482ccb601708b2e3f91e7
+  :scss  {:builds
           {:dev {:source-dir "src/scss"
                  :dest-dir   "target/generated/public/css"
                  :executable "sass"


Update dependencies

Update dependencies

--- project.clj
+++ project.clj
@@ -5,7 +5,7 @@
             :url "http://www.eclipse.org/legal/epl-v10.html"}

   :dependencies [[clj-glob "1.0.0" :exclusions [org.clojure/clojure]]
-                 [lein-npm "0.4.0" :exclusions [org.clojure/clojure]]]
+                 [lein-npm "0.5.0" :exclusions [org.clojure/clojure]]]

   :plugins [[jonase/eastwood "0.2.1" :exclusions [org.clojure/clojure]]
             [lein-kibit "0.0.8" :exclusions [org.clojure/clojure]]


0.1.0

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject employeerepublic/deferst "0.1.0-SNAPSHOT"
+(defproject employeerepublic/deferst "0.1.0"
   :description "a simple object system builder"
   :url "http://egithub.com/employeerepublic/deferst"
   :license {:name "Eclipse Public License"


use org.clojars.jds02006 tictag api

use org.clojars.jds02006 tictag api

--- project.clj
+++ project.clj
@@ -34,7 +34,7 @@
                  [org.clojure/core.async "0.2.395"]
                  [org.clojure/tools.cli "0.3.5"]
                  [org.clojure/java.jdbc "0.7.0-alpha1"]
-                 [tictagapi "0.1.0-SNAPSHOT"]
+                 [org.clojars.jds02006/tictagapi "0.1.0-SNAPSHOT"]
                  [reloaded.repl "0.2.3"]
                  [com.andrewmcveigh/cljs-time "0.5.0-alpha2"]
                  [day8.re-frame/http-fx "0.1.3"]


Add core.match

Add core.match

--- project.clj
+++ project.clj
@@ -6,7 +6,8 @@
                       :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies      [[org.clojure/clojure                          "1.7.0"]
                       [com.datastax.cassandra/cassandra-driver-core "2.1.6"]
-                      [com.datastax.cassandra/cassandra-driver-dse  "2.1.6"]]
+                      [com.datastax.cassandra/cassandra-driver-dse  "2.1.6"]
+                      [org.clojure/core.match                       "0.3.0-alpha4"]]
   :source-paths      ["src/clojure"]
   :test-paths        ["test/clojure" "test/java"]
   :java-source-paths ["test/java" "src/java"]


Updated dependencies

Updated dependencies

--- project.clj
+++ project.clj
@@ -41,7 +41,7 @@
                                    [midje          "1.6.3"]
                                    [clj-ns-browser "1.3.1"]
                                  ]
-                   :plugins      [[lein-midje "3.1.1"]]}   ; Don't remove this or travis-ci will assplode!
+                   :plugins      [[lein-midje "3.1.3"]]}   ; Don't remove this or travis-ci will assplode!
              :uberjar {:aot :all}}
   :uberjar-merge-with {#"META-INF/services/.*" [slurp str spit]}   ; Awaiting Leiningen 2.3.5 - see https://github.com/technomancy/leiningen/issues/1455
   :main alfresco-technical-validation.main


Bump to version 0.5.0

Bump to version 0.5.0

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject re-frame "0.5.0-alpha3"
+(defproject re-frame "0.5.0"
   :description  "A Clojurescript MVC-like Framework For Writing SPAs Using Reagent."
   :url          "https://github.com/Day8/re-frame.git"
   :license      {:name "MIT"}


Decrement version number

Decrement version number

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject nightmod "0.1.3-SNAPSHOT"
+(defproject nightmod "0.1.2"
   :description "A tool for making live-moddable games in Clojure"
   :url "https://github.com/oakes/Nightmod"
   :license {:name "Public Domain"


Revert "Bump ClojureScript dependency to 1.9.293." Fixes #122. Version 0.3.3.

This reverts commit 327711bb53c7ae509eda5b9fa446f83f0f48d981.

--- project.clj
+++ project.clj
@@ -1,9 +1,9 @@
-(defproject mozilla/datomish "0.3.3-SNAPSHOT"
+(defproject mozilla/datomish "0.3.3"
   :description "A persistent, embedded knowledge base inspired by Datomic and DataScript."
   :url "https://github.com/mozilla/datomish"
   :license {:name "Apache License, Version 2.0"
             :url "https://www.apache.org/licenses/LICENSE-2.0"}
-  :dependencies [[org.clojure/clojurescript "1.9.293"]
+  :dependencies [[org.clojure/clojurescript "1.9.229"]
                  [org.clojure/clojure "1.8.0"]
                  [org.clojure/core.async "0.2.385"]
                  [datascript "0.15.4"]


Latest cljsbuild

Latest cljsbuild

--- project.clj
+++ project.clj
@@ -6,10 +6,11 @@
   :dependencies [[org.clojure/clojure "1.5.1"]
                  [org.clojure/clojurescript "0.0-2156"]]
   :scm {:url "git@github.com:rm-hull/inkspot.git"}
-  :plugins [[lein-cljsbuild "1.0.1"]
+  :plugins [[lein-cljsbuild "1.0.2"]
             [com.birdseye-sw/lein-dalap "0.1.0"]]
-  :hooks [leiningen.dalap]
-  :source-paths ["src" "target/generated-src"]
+  :hooks [leiningen.dalap
+          leiningen.cljsbuild]
+  :source-paths ["src"]
   :cljsbuild {
     :repl-listen-port 9000
     :repl-launch-commands


Add antlr dependency

Add antlr dependency

--- project.clj
+++ project.clj
@@ -7,11 +7,13 @@
   :plugins [[lein-typed "0.3.5"]
             [lein-antlr "0.2.0"]]
   :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"}
+  :source-paths ["src/clj"]
   :java-source-paths ["src/java"]
   :dependencies [[org.clojure/clojure "1.6.0"]
                  [org.clojure/core.typed "0.2.77"]
                  [org.clojure/tools.cli "0.3.1"]
-                 [org.clojure/core.match "0.3.0-alpha4"]]
+                 [org.clojure/core.match "0.3.0-alpha4"]
+                 [org.antlr/antlr-runtime "3.5.2"]]
    :main jest.jest

    ;; Typed configs


Revert "Test commit from core to Kafka."

This reverts commit d89b02933cb282997ad7b890131599ccd9b4b18c.

[ci skip]

--- project.clj
+++ project.clj
@@ -5,7 +5,7 @@
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.7.0"]
                  ^{:voom {:repo "git@github.com:onyx-platform/onyx.git" :branch "master"}}
-                 [org.onyxplatform/onyx "0.7.3-20150822_210824-ga0dc570"]
+                 [org.onyxplatform/onyx "0.7.3-20150821_215046-g67feccf"]
                  [clj-kafka "0.2.8-0.8.1.1" :exclusions [org.apache.zookeeper/zookeeper zookeeper-clj]]
                  [cheshire "5.4.0"]
                  [zookeeper-clj "0.9.1" :exclusions [io.netty/netty org.apache.zookeeper/zookeeper]]]


Bump Clojure version to 1.7.0

Bump Clojure version to 1.7.0

No reason not to.

--- project.clj
+++ project.clj
@@ -12,7 +12,7 @@
                                    :username [:gpg :env/datomic_username]
                                    :password [:gpg :env/datomic_passphrase]}}

-  :dependencies [[org.clojure/clojure "1.7.0-RC1"]
+  :dependencies [[org.clojure/clojure "1.7.0"]
                  [org.clojure/clojurescript "0.0-3308"]
                  [medley "0.6.0"]
                  [com.stuartsierra/component "0.2.3"]


Add support for lein2

Add support for lein2

This removes the lein-marginalia plugin for lein2, but otherwise
everything is supported equally for both lein1 and lein2.

--- project.clj
+++ project.clj
@@ -1,5 +1,6 @@
 (require '[clojure.string :as s])
-(use '[clojure.java.shell :only (sh)])
+(use '[clojure.java.shell :only (sh)]
+     '[clojure.java.io :only (file)])

 (def version-string
   (memoize
@@ -35,6 +36,7 @@
                  [org.clojure/tools.logging "0.2.3"]
                  [org.clojure/tools.cli "0.2.1"]
                  [org.clojure/tools.nrepl "0.2.0-beta2"]
+                 [org.clojure/tools.namespace "0.1.3"]
                  [swank-clojure "1.4.0"]
                  [clj-stacktrace "0.2.4"]
                  [metrics-clojure "0.7.0" :exclusions [org.clojure/clojure org.slf4j/slf4j-api]]
@@ -73,6 +75,9 @@
                      ;; WebAPI support libraries.
                      [ring-mock "0.1.1"]]

+  :profiles {:dev {:resource-paths ["test-resources"],
+                   :dependencies [[ring-mock "0.1.1"]]}}
+
   :jar-exclusions [#"leiningen/"]
   :manifest {"Build-Version" ~(version-string)}


Update deps

Update deps

- sesame-runtime
- commons-logging
- data.csv
- clj-excel
- pantomime

--- project.clj
+++ project.clj
@@ -7,22 +7,18 @@
   :deploy-repositories [["releases" :clojars]]

   :dependencies [[org.clojure/clojure "1.7.0"]
-                 [org.openrdf.sesame/sesame-runtime "2.7.16"
-                  :exclusions [org.openrdf.sesame/sesame-repository-manager]]
-
+                 [org.openrdf.sesame/sesame-runtime "2.7.16"]
                  [org.clojure/tools.logging "0.3.1"]

                  [grafter/url "0.2.1"]

-                 ;; Shouldn't need this, but somehow excluded and required by SPARQLRepository
-                 [commons-logging "1.1.1"]
-                 [org.clojure/data.csv "0.1.2"]
-                 [com.outpace/clj-excel "0.0.6" :exclusions [commons-codec]]
+                 [commons-logging "1.2"] ;; Shouldn't need this, but somehow excluded and required by SPARQLRepository
+                 [org.clojure/data.csv "0.1.3"]
+                 [com.outpace/clj-excel "0.0.9" :exclusions [commons-codec]]
                  [me.raynes/fs "1.4.6"]
                  [potemkin "0.4.1"]
                  [incanter/incanter-core "1.5.5" :exclusions [net.sf.opencsv/opencsv commons-codec]]
-                 [net.sf.corn/corn-cps "1.1.7"] ;; classpath scanner
-                 [com.novemberain/pantomime "2.4.0"] ;; mimetypes
+                 [com.novemberain/pantomime "2.8.0"] ;; mimetypes
                  ]

   :codox {:defaults {:doc "FIXME: write docs"
@@ -68,7 +64,7 @@
                                                                 org.codehaus.plexus/plexus-utils]]]

                    :dependencies [[com.aphyr/prism "0.1.3"]
-                                  [prismatic/schema "0.4.3"]
+                                  [prismatic/schema "1.0.4"]
                                   [criterium "0.4.3"]]

                    :env {:dev true}}})


bumped up version

bumped up version

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject reagent/lein-template "0.3.6"
+(defproject reagent/lein-template "0.3.7"
   :description "A Leiningen template for a ClojureScript setup with Figwheel, Austin, and Reagent."
   :url "https://github.com/reagent-project/reagent-template"
   :license {:name "MIT License"


Version 3.2.0-preview1

Version 3.2.0-preview1

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject neko "3.1.2-SNAPSHOT"
+(defproject neko "3.2.0-preview1"
   :description "Neko is a toolkit designed to make Android development using Clojure easier and more fun."
   :url "https://github.com/clojure-android/neko"
   :license {:name "Eclipse Public License"