CMR-6499: Change shapefile simplification code to be consistent

--- search-app/src/cmr/search/middleware/shapefile_simplification.clj
+++ search-app/src/cmr/search/middleware/shapefile_simplification.clj
@@ -121,7 +121,7 @@
 (defn- simplify-data
   "Given an ArrayList of Features simplify the Features and return stats about the process
   along with a new shapefile info map to replace the one in the search reqeust"
-  [filename ^ArrayList features feature-type mime-type]
+  [filename ^ArrayList features mime-type]
   (let [[simplified-features stats] (iterative-simplify features mime-type)
         [original-point-count new-point-count] stats]
     [[original-point-count
@@ -148,32 +148,19 @@
                     temp-dir)
           data-store (FileDataStoreFinder/getDataStore shp-file)
           feature-source (.getFeatureSource data-store)
-          feature-type (.getSchema feature-source)
           features (.getFeatures feature-source)
-          feature-count (shapefile/error-if (.size features)
-                                            #(< % 1)
-                                            "Shapefile has no features"
-                                            temp-dir)
-          _ (shapefile/error-if feature-count
-                                #(> % (shapefile/max-shapefile-features))
-                                (format "Shapefile feature count [%d] exceeds the %d feature limit"
-                                        feature-count
-                                        (shapefile/max-shapefile-features))
-                                nil)
-          _ (debug (format "Found [%d] features" feature-count))
-          iterator (.features features)]
+          iterator (.features features)
+          feature-list (ArrayList.)]
       (try
-        (loop [features (ArrayList.)]
-          (if (.hasNext iterator)
-            (let [feature (.next iterator)]
-              (.add features feature)
-              (recur features))
-            (simplify-data filename features feature-type mt/shapefile)))
-        (finally (do
-                   (.close iterator)
-                   (-> data-store .getFeatureReader .close)
-                   (.delete temp-dir)
-                   (.delete file)))))
+        (while (.hasNext iterator)
+          (let [feature (.next iterator)]
+            (.add feature-list feature)))
+            (simplify-data filename feature-list mt/shapefile)
+        (finally
+          (.close iterator)
+          (-> data-store .getFeatureReader .close)
+          (.delete temp-dir)
+          (.delete file))))
     (catch Exception e
       (let [{:keys [type errors]} (ex-data e)]
         (if (and type errors)
@@ -188,16 +175,13 @@
     (let [file (:tempfile shapefile-info)
           filename (:filename shapefile-info)
           input-stream (FileInputStream. file)
-          parser (PullParser. (KMLConfiguration.) input-stream SimpleFeature)]
+          parser (PullParser. (KMLConfiguration.) input-stream SimpleFeature)
+          feature-list (ArrayList.)]
       (try
-        (loop [features (ArrayList.)]
-          (if-let [feature (.parse parser)]
-            (do
-              (.add features feature)
-              (recur features))
-            (if-let [first-feature (when (not (.isEmpty features)) (.get features 0))]
-              (simplify-data filename features (.getFeatureType first-feature) mt/kml)
-              (errors/throw-service-error :bad-request "KML file has no features"))))
+        (util/while-let [feature (.parse parser)]
+          (when (> (feature-point-count feature) 0)
+            (.add feature-list feature)))
+        (simplify-data filename feature-list mt/kml)
         (finally
           (.delete file))))
     (catch Exception e
@@ -217,24 +201,18 @@
           url (URLs/fileToUrl file)
           data-store (GeoJSONDataStore. url)
           feature-source (.getFeatureSource data-store)
-          feature-type (.getSchema feature-source)
           features (.getFeatures feature-source)
-          feature-count (shapefile/error-if (.size features)
-                                            #(< % 1)
-                                            "GeoJSON has no features"
-                                            nil)
-          iterator (.features features)]
+          iterator (.features features)
+          feature-list (ArrayList.)]
       (try
-        (loop [features (ArrayList.)]
-          (if (.hasNext iterator)
-            (let [feature (.next iterator)]
-              (.add features feature)
-              (recur features))
-            (simplify-data filename features feature-type mt/geojson)))
-        (finally (do
-                   (.close iterator)
-                   (-> data-store .getFeatureReader .close)
-                   (.delete file)))))
+        (while (.hasNext iterator)
+          (let [feature (.next iterator)]
+            (.add feature-list feature)))
+        (simplify-data filename feature-list mt/geojson)
+        (finally
+          (.close iterator)
+          (-> data-store .getFeatureReader .close)
+          (.delete file))))
     (catch Exception e
       (let [{:keys [type errors]} (ex-data e)]
         (if (and type errors)
@@ -263,7 +241,7 @@
   to point to the new (reduced) shapefile"
   [request]
   (when (= "true" (get-in request [:params "simplify-shapefile"]))
-    (if-let [tmp-file (get-in request [:params "shapefile" :tempfile])]
+    (if (get-in request [:params "shapefile" :tempfile])
       (simplify (get-in request [:params "shapefile"]))
       (errors/throw-service-error :bad-request "Missing shapefile"))))

@@ -271,7 +249,7 @@
   "Adds shapefile simplification header to response when shapefile simplication was
   requested."
   [handler default-format-fn]
-  (fn [{context :request-context :as request}]
+  (fn [{_context :request-context :as request}]
     (try
       (if-let [[[original-point-count new-point-count] result] (simplify-shapefile request)]
         (-> (assoc-in request [:params "shapefile"] result)


fixed some gpg

fixed some gpg

--- src/dda/pallet/dda_user_crate/infra/gpg.clj
+++ src/dda/pallet/dda_user_crate/infra/gpg.clj
@@ -41,28 +41,28 @@
         {:keys [public-key private-key passphrase]} trusted-key
         user-home (user-env/user-home-dir user-name)]
     (actions/remote-file
-      (str user-home "pub.key")
+      (str user-home "/pub.key")
       :content public-key
       :mode "600"
       :owner user-name
       :group user-name
       :action :create)
     (actions/remote-file
-      (str user-home "priv.key")
+      (str user-home "/priv.key")
       :content private-key
       :mode "600"
       :owner user-name
       :group user-name
       :action :create)
     (actions/directory
-      (str user-home ".gnupg")
+      (str user-home "/.gnupg")
       :mode "700"
       :owner user-name
       :group user-name
       :action :create)
     ;(actions/exec-script* "cd ~/.gnupg && echo \"allow-loopback-pinentry\"  >> gpg-agent.conf")
     (actions/remote-file
-      (str user-home ".gnupg/gpg-agent.conf")
+      (str user-home "/.gnupg/gpg-agent.conf")
       :mode "600"
       :content "allow-loopback-pinentry"
       :owner user-name
@@ -73,10 +73,9 @@
       :script-dir user-home
       :script-env {:HOME user-home}}
      (actions/exec-checked-script
-      "enable-and-start-vnc-service"
-      ("gpgconf" "--kill" "gpg-agent")
-      ("gpg2" "--import" ~(str user-home "pub.key"))
+      "import & trust gpg key"
+      ("gpg2" "--import" ~(str user-home "/pub.key"))
       ("echo" ~passphrase "|" "gpg2" "--pinentry-mode loopback"
               "--batch --passphrase-fd 0"
-              "--import" ~(str user-home "priv.key"))
+              "--import" ~(str user-home "/priv.key"))
       ("/usr/lib/gpg-trust-all.sh")))))


Extract function

Extract function

--- src/app/cljs/one/repmax/datastore_configuration/view.cljs
+++ src/app/cljs/one/repmax/datastore_configuration/view.cljs
@@ -47,12 +47,7 @@
     (d/set-value! (d/by-id "api-key-input") (:api-key datastore-configuration))
     (d/set-value! (d/by-id "database-input") (:database datastore-configuration))
     (add-event-listener-for-showing-more-info)
-    (event/listen (d/by-id "datastore-configuration-form-button") ; TODO extract fn
-                  event-type/CLICK
-                  #(dispatch/fire :action
-                                  {:action   :datastore-configuration/update
-                                   :api-key  (d/value (d/by-id "api-key-input"))
-                                   :database (d/value (d/by-id "database-input"))}))))
+    (add-event-listener-for-submitting-form)))

 (defmulti render-datastore-configuration-state
   (fn [datastore-configuration] (:state datastore-configuration)))
@@ -112,6 +107,14 @@
   (enable "database-input")
   (enable "datastore-configuration-form-button"))

+(defn add-event-listener-for-submitting-form []
+  (event/listen (d/by-id "datastore-configuration-form-button")
+                event-type/CLICK
+                #(dispatch/fire :action
+                                {:action   :datastore-configuration/update
+                                 :api-key  (d/value (d/by-id "api-key-input"))
+                                 :database (d/value (d/by-id "database-input"))})))
+
 (defn add-event-listener-for-showing-more-info []
   (doseq [node (d/nodes (d/by-class "tell-me-more"))]
     (event/listen-once node


Using new code generating function

Using new code generating function

--- src/wishlistd/models/queries.clj
+++ src/wishlistd/models/queries.clj
@@ -7,6 +7,8 @@
          :subname "//localhost:5432/cwl"
          :user "cwl"
          :password "wish"})
+
+(def code-length 8)

 ;wishlist
 ;[:id :serial "PRIMARY KEY"]
@@ -43,7 +45,7 @@

 (defn insert-wishlist [wishlist]
   (let [inserted (helper-insert-wishlist wishlist) ; make wishlist
-        code (generate-code (:id inserted)) ; make code
+        code (random-code code-length) ; make code
         finished (assoc inserted :code code)] ; add code to list
     (update-wishlist finished)
     (get-wishlist finished)))


improves websocket last-request-time test (#1525)

--- waiter/integration/waiter/websocket_integration_test.clj
+++ waiter/integration/waiter/websocket_integration_test.clj
@@ -14,7 +14,8 @@
 ;; limitations under the License.
 ;;
 (ns waiter.websocket-integration-test
-  (:require [clj-time.core :as t]
+  (:require [clj-time.coerce :as tc]
+            [clj-time.core :as t]
             [clojure.core.async :as async]
             [clojure.data.json :as json]
             [clojure.string :as str]
@@ -458,6 +459,7 @@
           inter-request-interval-ms (+ metrics-sync-interval-ms 1000)
           auth-cookie-value (auth-cookie waiter-url)
           waiter-headers (assoc (kitchen-request-headers)
+                           :x-waiter-debug "true"
                            :x-waiter-metric-group "waiter_ws_test"
                            :x-waiter-name (rand-name))
           _ (make-kitchen-request waiter-url waiter-headers :method :get)
@@ -475,6 +477,7 @@
         (let [response-promise (promise)
               connect-start-time-ms (System/currentTimeMillis)
               connect-end-time-ms-atom (atom connect-start-time-ms)
+              request-headers (assoc waiter-headers "x-cid" (utils/unique-identifier))
               connection (ws-client/connect!
                            (websocket-client-factory)
                            (ws-url waiter-url "/websocket-auth")
@@ -491,22 +494,30 @@
                                (async/close! out)
                                (deliver response-promise :done)))
                            {:middleware (fn [_ ^UpgradeRequest request]
-                                          (websocket/add-headers-to-upgrade-request! request waiter-headers)
+                                          (websocket/add-headers-to-upgrade-request! request request-headers)
                                           (add-auth-cookie request auth-cookie-value))})
               [close-code error] (connection->ctrl-data connection)]
           (is (= :qbits.jet.websocket/close close-code))
           (is (= websocket-1000-normal error))
           (is (= :done (deref response-promise (* 2 num-iterations inter-request-interval-ms) :timed-out)))
-          (Thread/sleep (* 3 metrics-sync-interval-ms))
+          (let [min-metrics-sync-interval-ms 1000] ;; avoid sleeping for toon short a duration
+            (-> metrics-sync-interval-ms (* 3) (max min-metrics-sync-interval-ms) (Thread/sleep)))
           (let [connection-duration-ms (- @connect-end-time-ms-atom connect-start-time-ms)
                 websocket-duration-ms (* num-iterations inter-request-interval-ms)
                 minimum-last-request-time-duration-ms (+ connection-duration-ms websocket-duration-ms)
                 minimum-last-request-time (t/plus first-request-time-header (t/millis minimum-last-request-time-duration-ms))
-                service-last-request-time (service-id->last-request-time waiter-url service-id)]
-            (is (pos? (.getMillis service-last-request-time)))
-            (is (or (t/before? minimum-last-request-time service-last-request-time)
-                    (t/equal? minimum-last-request-time service-last-request-time))
-                (str [minimum-last-request-time service-last-request-time]))))))))
+                service-last-request-time (service-id->last-request-time waiter-url service-id)
+                assertion-message (str {:durations {:connection-duration-ms connection-duration-ms
+                                                    :websocket-duration-ms websocket-duration-ms}
+                                        :request-headers request-headers
+                                        :service-id service-id
+                                        :times {:minimum-last-request-time minimum-last-request-time
+                                                :service-last-request-time service-last-request-time
+                                                :ws-connect-end-time-ms (tc/from-long @connect-end-time-ms-atom)
+                                                :ws-connect-start-time (tc/from-long connect-start-time-ms)}})]
+            (is (some? service-last-request-time) assertion-message)
+            (is (pos? (.getMillis service-last-request-time)) assertion-message)
+            (is (t/after? service-last-request-time minimum-last-request-time) assertion-message)))))))

 (deftest ^:parallel ^:integration-fast ^:explicit test-request-socket-timeout
   (testing-using-waiter-url


Add constants for days and months

Add constants for days and months

--- src/tick/alpha/api.clj
+++ src/tick/alpha/api.clj
@@ -9,7 +9,7 @@
    [tick.interval :as interval]
    [clojure.set :as set])
   (:import
-   [java.time Duration ZoneId LocalTime LocalDate]))
+   [java.time Duration ZoneId LocalTime LocalDate DayOfWeek Month]))

 ;; This API is optimises convenience, API stability and (type) safety
 ;; over performance. Where performance is critical, use tick.core and
@@ -30,6 +30,29 @@
 (defn today [] (core/today))
 (defn tomorrow [] (core/tomorrow))
 (defn yesterday [] (core/yesterday))
+
+;; Constants
+
+(def monday DayOfWeek/MONDAY)
+(def tuesday DayOfWeek/TUESDAY)
+(def wednesday DayOfWeek/WEDNESDAY)
+(def thursday DayOfWeek/THURSDAY)
+(def friday DayOfWeek/FRIDAY)
+(def saturday DayOfWeek/SATURDAY)
+(def sunday DayOfWeek/SUNDAY)
+
+(def january Month/JANUARY)
+(def february Month/FEBRUARY)
+(def march Month/MARCH)
+(def april Month/APRIL)
+(def may Month/MAY)
+(def june Month/JUNE)
+(def july Month/JULY)
+(def august Month/AUGUST)
+(def september Month/SEPTEMBER)
+(def october Month/OCTOBER)
+(def november Month/NOVEMBER)
+(def december Month/DECEMBER)

 ;; Constructors


Add warning about github rate-limiting

Add warning about github rate-limiting

to source cache clearing not

--- src-cljs/frontend/components/project_settings.cljs
+++ src-cljs/frontend/components/project_settings.cljs
@@ -289,7 +289,7 @@
                              :result-path
                              (conj state/project-data-path :source-cache-clear))))
           [:p "CircleCI saves a copy of your source code on our system and pulls only changes since the last build on each branch."]
-          [:p [:b "NOTE: "] "Clearing your source cache will cause the next build to download a fresh copy of your source. In some cases this can add considerable time to that build."]
+          [:p [:b "NOTE: "] "Clearing your source cache will cause the next build to download a fresh copy of your source. In some cases this can add considerable time to that build.  Doing this too frequently or when you have a large number of high parallelism builds also carries some risk of becoming rate-limited by github, which will prevent your builds from being able to download source until the rate-limit expires."]
           (clear-cache-button "source" project-data owner)]]))))

 (defn env-vars [project-data owner]


registered-repos api test cases

registered-repos api test cases

--- cloc-web/test/cloc_web/core_test.clj
+++ cloc-web/test/cloc_web/core_test.clj
@@ -32,25 +32,61 @@
       r/delete
       (r/run @db-conn)))

+(defmacro scenario [aside & body] `(do ~@body))
+
 (use-fixtures :once setup-server)
 (use-fixtures :each setup-each)

 (deftest register-with-unauthorized-user
   (testing "no session"
-    (is 401 (:status (client/post (str url "/user/repo/register") {:accept :json
-                                                                   :throw-exceptions false}))))
+    (is (= 401 (:status (client/post (str url "/user/repo/register") {:accept :json
+                                                                      :throw-exceptions false})))))

   (testing "invalid session id"
     (with-redefs [clj-http.client/get (fn [& param] {:status 400
                                                      :body {:error ""}})]
-      (is 401 (:status (client/post (str url "/user/repo/register") {:accept :json
-                                                                     :throw-exceptions false
-                                                                     :cookies {"session_id" {:discard true :value (jwt-token "debug_token" {:expires (-> 28 days)})}}}))))))
+      (is (= 401 (:status (client/post (str url "/user/repo/register") {:accept :json
+                                                                        :throw-exceptions false
+                                                                        :cookies {"session_id" {:discard true :value (jwt-token "debug_token" {:expires (-> 28 days)})}}})))))))

 (deftest register-with-authorized-user
   (with-redefs [clj-http.client/get (fn [& param] {:status 200
                                                    :body {:login "0of"}})]
-    (is 200 (:status (client/post (str url "/user/repo/register") {:accept :json
-                                                                   :throw-exceptions false
-                                                                   :cookies {"session_id" {:discard true :value (jwt-token "debug_token" {:expires (-> 28 days)})}}})))))
+    (is (= 200 (:status (client/post (str url "/user/repo/register") {:accept :json
+                                                                      :throw-exceptions false
+                                                                      :cookies {"session_id" {:discard true :value (jwt-token "debug_token" {:expires (-> 28 days)})}}}))))))

+(deftest list-registered-repos-with-unauthorized-user
+  (testing "no session"
+    (is (= 401 (:status (client/post (str url "/user/registered_repos") {:accept :json
+                                                                         :throw-exceptions false})))))
+
+  (testing "invalid session id"
+    (with-redefs [clj-http.client/get (fn [& param] {:status 400
+                                                     :body {:error ""}})]
+      (is (= 401 (:status (client/post (str url "/user/registered_repos") {:accept :json
+                                                                           :throw-exceptions false
+                                                                           :cookies {"session_id" {:discard true :value (jwt-token "debug_token" {:expires (-> 28 days)})}}})))))))
+
+(deftest list-registered-repos-with-authorized-user
+  (scenario "register repos"
+    (-> (r/table "users")
+        (r/insert {:id "github/user/target1"
+                   :user "user"
+                   :filter "*"
+                   :lang "SUM"})
+        (r/run @db-conn))
+
+    (-> (r/table "users")
+        (r/insert {:id "github/user/target2"
+                   :user "user"
+                   :filter "*"
+                   :lang "SUM"})
+        (r/run @db-conn)))
+
+  (with-redefs [clj-http.client/get (fn [& param] {:status 200
+                                                   :body {:login "0of"}})]
+    (is (= 2 (count (:body (client/post (str url "/user/registered_repos") {:accept :json
+                                                                            :throw-exceptions false
+                                                                            :cookies {"session_id" {:discard true :value (jwt-token "debug_token" {:expires (-> 28 days)})}}})))))))
+


perform schema validation in dev repl

perform schema validation in dev repl

--- dev/user.clj
+++ dev/user.clj
@@ -1,7 +1,10 @@
 (ns user
   (:require [coffee-table.component.database :as db]
             [coffee-table.system :refer [new-system]]
-            [reloaded.repl :refer [system init start stop go reset reset-all]]))
+            [reloaded.repl :refer [system init start stop go reset reset-all]]
+            [schema.core :as s]))
+
+(s/set-fn-validation! true)

 (reloaded.repl/set-init! #(new-system :dev))


Fix changelog name concurrency issue

Fix changelog name concurrency issue

--- src/main/clojure/pdok/featured/timeline.clj
+++ src/main/clojure/pdok/featured/timeline.clj
@@ -367,8 +367,9 @@

 (def o ^{:private true} (Object.))
 (defn unique-epoch []
-  (Thread/sleep 1)                                          ;; ugh, ugly
-  (locking o (System/currentTimeMillis)))
+  (locking o
+    (Thread/sleep 1) ;; ugh, ugly
+    (System/currentTimeMillis)))

 (defn ^{:dynamic true} *changelog-name* [dataset collection]
   (str (unique-epoch) "-" dataset "-" collection ".changelog"))


Make a few small improvements

Make a few small improvements

--- super-koalio/desktop/src-common/super_koalio/entities.clj
+++ super-koalio/desktop/src-common/super_koalio/entities.clj
@@ -20,7 +20,7 @@
          :x 20
          :y 10
          :is-me? true
-         :can-jump? true
+         :can-jump? false
          :direction :right))

 (defn move
@@ -60,16 +60,14 @@

 (defn prevent-move
   [screen {:keys [x y x-change y-change] :as entity}]
-  (if (and (= 0 x-change) (= 0 y-change))
-    entity
-    (let [old-x (- x x-change)
-          old-y (- y y-change)
-          entity-x (assoc entity :y old-y)
-          entity-y (assoc entity :x old-x)
-          up? (> y-change 0)]
-      (merge entity
-             (when (u/get-touching-tile screen entity-x "walls")
-               {:x-velocity 0 :x-change 0 :x old-x})
-             (when-let [tile (u/get-touching-tile screen entity-y "walls")]
-               {:y-velocity 0 :y-change 0 :y old-y
-                :can-jump? (not up?) :to-destroy (when up? tile)})))))
+  (let [old-x (- x x-change)
+        old-y (- y y-change)
+        entity-x (assoc entity :y old-y)
+        entity-y (assoc entity :x old-x)
+        up? (> y-change 0)]
+    (merge entity
+           (when (u/get-touching-tile screen entity-x "walls")
+             {:x-velocity 0 :x-change 0 :x old-x})
+           (when-let [tile (u/get-touching-tile screen entity-y "walls")]
+             {:y-velocity 0 :y-change 0 :y old-y
+              :can-jump? (not up?) :to-destroy (when up? tile)}))))


figwheel.repl: fix minor printing error

figwheel.repl: fix minor printing error

--- figwheel-repl/src/figwheel/repl.cljc
+++ figwheel-repl/src/figwheel/repl.cljc
@@ -359,7 +359,7 @@
                                  result-value)
                   output-str (str sb)]
               (when print-to-console?
-                (js/setTimeout #(out-print :console output-str) 0))
+                (js/setTimeout #(out-print :console [output-str]) 0))
               {:status :success
                :out output-str
                :ua-product ua-product


CMR-294: Added tests for MENDS ISO ingest.

--- test/cmr/system_int_test/search/collection_search_format_test.clj
+++ test/cmr/system_int_test/search/collection_search_format_test.clj
@@ -183,6 +183,24 @@
            [-180 90 180 -90] [g2]
            [0 90 180 -90] []
            [-180 90 0 -90] [g2]))))
+
+(deftest iso-ingest
+  (let [coll1 (d/ingest "PROV1" (dc/collection {:short-name "S1"
+                                                :version-id "V1"})
+                        :iso)
+        coll2 (d/ingest "PROV2" (dc/collection {:short-name "S2"
+                                                :version-id "V2"})
+                        :iso-mends)]
+    (index/refresh-elastic-index)
+
+    (testing "Finding refs ingested in different formats"
+      (are [search expected]
+           (d/refs-match? expected (search/find-refs :collection search))
+           {} [coll1 coll2]
+           {:short-name "S1"} [coll1]
+           {:short-name "S2"} [coll2]
+           {:version "V1"} [coll1]
+           {:version ["V1" "V2"]} [coll1 coll2]))))

 (deftest search-collection-atom-and-json
   (let [ru1 (dc/related-url "GET DATA" "http://example.com")


Write a bunch of cache store tests.

Write a bunch of cache store tests.

--- test/blocks/store/cache_test.clj
+++ test/blocks/store/cache_test.clj
@@ -1,11 +1,76 @@
 (ns blocks.store.cache-test
   (:require
+    [blocks.core :as block]
     (blocks.store
-      [cache :refer [cache-store]]
+      [cache :as cache :refer [cache-store]]
       [memory :refer [memory-store]]
       [tests :as tests :refer [test-block-store]])
     [clojure.test :refer :all]
-    [com.stuartsierra.component :as component]))
+    [com.stuartsierra.component :as component]
+    [multihash.core :as multihash]
+    [puget.printer :as puget]))
+
+
+(defn new-cache
+  "Helper function to construct a fresh cache store backed by empty memory
+  stores."
+  [size-limit]
+  (cache-store size-limit
+    :primary (memory-store)
+    :cache (memory-store)))
+
+
+(deftest store-construction
+  (is (thrown? IllegalArgumentException (cache-store nil)))
+  (is (thrown? IllegalArgumentException (cache-store 0)))
+  (is (thrown? IllegalArgumentException (cache-store 512 :max-block-size "foo")))
+  (is (thrown? IllegalArgumentException (cache-store 512 :max-block-size 0)))
+  (is (satisfies? block/BlockStore (cache-store 512 :max-block-size 128))))
+
+
+(deftest store-lifecycle
+  (let [store (new-cache 1024)]
+    (is (thrown? IllegalStateException
+                 (component/start (assoc store :primary nil)))
+        "starting cache without primary throws an exception")
+    (is (thrown? IllegalStateException
+                 (component/start (assoc store :cache nil)))
+        "starting cache without cache throws an exception")
+    (is (= store (component/start (component/start store)))
+        "starting cache store again is a no-op")
+    (is (= store (component/stop store))
+        "stopping cache store is a no-op")))
+
+
+(deftest uninitialized-store
+  (let [store (new-cache 1024)]
+    (testing "no primary store"
+      (is (thrown? IllegalStateException (block/list (assoc store :primary nil)))))
+    (testing "no cache store"
+      (is (thrown? IllegalStateException (block/list (assoc store :cache nil)))))
+    (testing "not started"
+      (is (thrown? IllegalStateException (block/list store))))))
+
+
+(deftest extant-cache-contents
+  (let [store (new-cache 1024)
+        content (tests/populate-blocks! (:cache store) 10 64)
+        store' (component/start store)]
+    (is (every? #(block/stat (:cache store) %) (keys content))
+        "all blocks should still be present in store")
+    (is (every? #(contains? (:priorities @(:state store)) %) (keys content))
+        "all blocks should have an entry in the priority map")))
+
+
+(deftest space-reaping
+  (let [store (new-cache 1024)
+        content (tests/populate-blocks! (:cache store) 32 1024)
+        store (component/start store)]
+    (is (< 1024 (:total-size @(:state store)))
+        "has more than size-limit blocks cached")
+    (cache/reap! store 512)
+    (is (<= (:total-size @(:state store)) 512)
+        "reap cleans up at least the desired free space")))

 (deftest ^:integration test-cache-store
@@ -19,19 +84,4 @@
     (test-block-store
       "cache-store" store
       :max-size 4096
-      :blocks 50)
-    (is (= store (component/start (component/start store)))
-        "starting cache store again is a no-op")
-    (is (= store (component/stop store))
-        "starting cache store again is a no-op"))
-  (let [size-limit (* 16 1024)
-        primary (memory-store)
-        cache (memory-store)
-        store (cache-store size-limit
-                :primary primary
-                :cache cache)]
-    (tests/populate-blocks! cache 50 1536)
-    (test-block-store
-      "cache-store" store
-      :max-size 4096
       :blocks 50)))


fix bad test name, overlaps with standard ns

--- test/crucible/resources_test.clj
+++ test/crucible/resources_test.clj
@@ -3,7 +3,7 @@
             [crucible.resources :refer :all]
             [crucible.resources.aws.ec2 :refer [eip]]))

-(deftest test
+(deftest test-resources

   (testing "minimal custom resource"
     (is (= {"Type" "Custom::MyResource"


Fix conflicts tests, and one other test

Fix conflicts tests, and one other test

--- test/dependable/resolve_test.clj
+++ test/dependable/resolve_test.clj
@@ -47,7 +47,7 @@
         18
         "e_loc18"
         [
-         [(present "d")]
+         [(absent "d")]
          ])
        repo-info
        {"a"
@@ -161,41 +161,32 @@
               query
               :present-packages {"a" package-a20})
              [:successful #{}])))
-        )
-
-  (deftest conflicts
-    (testing (str "Find a package which conflicts with another "
-                  "package also to be installed.")
-      (is (= (resolve-dependencies
-              [{:id "d"}
-               {:id "e"}]
-              query)
-             [:unsuccessful ["e"]])))
-    (testing (str "Find a package which conflicts with a package "
-                  "marked a priori as conflicting.")
-      (is (= (resolve-dependencies
-              [{:id "a"}
-               {:id "d"}]
-              query
-              :conflicts {"d" nil})
-             [:unsuccessful ["d"]])))
-    (testing (str "Find a package which conflicts with a package "
-                  "marked a priori as conflicting with something "
-                  "already installed.")
-      (is (= (resolve-dependencies
-              [{:id "d"}]
-              query
-              :present-packages {"a" 11}
-              :conflicts {"d" nil})
-             [:unsuccessful ["d"]])))
-
-    (testing (str "Find a package which conflicts with another "
-                  "package but not at its current version")
-      (is (= (resolve-dependencies
-              [{:id "d"}]
-              query
-              :conflicts {"d" #(< % 22)})
-             [:successful #{package-d22}])))))
+    )
+
+  (deftest ^:resolve-basic conflicts
+    (let [dclause [(present "d")]]
+      (testing (str "Find a package which conflicts with another "
+                    "package also to be installed.")
+               (is (= (resolve-dependencies
+                        [dclause
+                         [(present "e")]]
+                        query)
+                      [:unsuccessful dclause])))
+      (testing (str "Find a package which conflicts with a package "
+                    "marked a priori as conflicting.")
+               (is (= (resolve-dependencies
+                        [dclause
+                         [(present "a" #(<= (:version %) 25))]]
+                        query
+                        :conflicts {"d" [nil]})
+                      [:unsuccessful dclause])))
+      (testing (str "Find a package which conflicts with another "
+                    "package but not at its current version")
+        (is (= (resolve-dependencies
+                [dclause]
+                query
+                :conflicts {"d" [#(< (:version %) 22)]})
+               [:successful #{package-d22}]))))))

 #_(deftest ^:resolve-basic requires


Drop person selection when fiddling with filters

--- frontend/src/faceboard/commands.cljs
+++ frontend/src/faceboard/commands.cljs
@@ -126,20 +126,24 @@
     (model/toggle-set [:ui :filters :expanded-set] filter-name)))

 (defmethod handle-command :filter-select-country [_ country-code]
+  (router/switch-person nil)
   (let [was-selected? (contains? (get-in @app-state [:ui :filters :active :countries]) country-code)]
     (transform-app-state
       (model/set [:ui :filters :active :countries] (if was-selected? #{} #{country-code})))))

 (defmethod handle-command :filter-shift-select-country [_ country-code]
+  (router/switch-person nil)
   (transform-app-state
     (model/toggle-set [:ui :filters :active :countries] country-code)))

 (defmethod handle-command :filter-select-tag [_ tag]
+  (router/switch-person nil)
   (let [was-selected? (contains? (get-in @app-state [:ui :filters :active :tags]) tag)]
     (transform-app-state
       (model/set [:ui :filters :active :tags] (if was-selected? #{} #{tag})))))

 (defmethod handle-command :filter-shift-select-tag [_ tag]
+  (router/switch-person nil)
   (transform-app-state
     (model/toggle-set [:ui :filters :active :tags] tag)))


delete obsolete comment

delete obsolete comment

--- src/main/clojure/clojure/test/check/generators.clj
+++ src/main/clojure/clojure/test/check/generators.clj
@@ -79,7 +79,6 @@
   [gens]
   (make-gen
    (fn [rnd size]
-     ;; could make this lazy once we have immutable RNGs
      (mapv #(call-gen % %2 size) gens (random/split-n rnd (count gens))))))

 ;; Exported generator functions


[#9480] Fix cutting of the last char in blockquote

--- src/status_im/ui/screens/chat/message/message.cljs
+++ src/status_im/ui/screens/chat/message/message.cljs
@@ -178,7 +178,7 @@
     "blockquote"
     (conj acc [react/view (style/blockquote-style (and outgoing (not pinned)))
                [react/text-class (style/blockquote-text-style (and outgoing (not pinned)))
-                (.substring literal 0 (dec (.-length literal)))]])
+                (.substring literal 0 (.-length literal))]])

     "codeblock"
     (conj acc [react/view {:style style/codeblock-style}


improve logging

improve logging


fix typo

fix typo

--- jar-placement-lib/src/sixsq/slipstream/placement/core.clj
+++ jar-placement-lib/src/sixsq/slipstream/placement/core.clj
@@ -115,8 +115,7 @@
   (format "schema-org:descriptionVector/schema-org:vcpu>=%sandschema-org:descriptionVector/schema-org:ram>=%sandschema-org:descriptionVector/schema-org:disk>=%s"
           (:cpu.nb component)
           (:ram.GB component)
-          (:disk.GB component)
-          "bob"))
+          (:disk.GB component)))

 (defn cimi-filter-policy
   [connectors component]


Extract prefix

Extract prefix

--- src/caesium/binding.clj
+++ src/caesium/binding.clj
@@ -52,6 +52,11 @@

 (assert (#{0 1} (.sodium_init sodium)))

+(defn prefix
+  "Gets the parts of the current namespace, minus the leading `caesium`."
+  []
+  (-> *ns* ns-name str (s/split #"\.") rest vec))
+
 (defmacro defconsts
   "Given constant names (syms) in the C pseudo-namespace corresponding
   to the current namespace, call the corresponding libsodium function
@@ -61,7 +66,7 @@
     `(do
        ~@(for [const consts]
            (let [name (-> const name (s/replace "-" "_") symbol)
-                 call (->> name (conj prefix) (s/join "_") (str ".") symbol)]
+                 call (->> name (conj (prefix)) (s/join "_") (str ".") symbol)]
              `(def ~const (~call sodium)))))))


Adapt brightness for use with p5js

Adapt brightness for use with p5js

--- src/cljc/quil/core.cljc
+++ src/cljc/quil/core.cljc
@@ -841,7 +841,7 @@
   brightness
   "Extracts the brightness value from a color. Returns a float."
   [color]
-  (.brightness (current-graphics) (unchecked-int color)))
+  (.brightness (current-graphics) color))

 (defn
   ^{:requires-bindings true


Add test for reassigning of prefixes

Add test for reassigning of prefixes

--- src/test/clojure/clojure/data/xml/test_names.clj
+++ src/test/clojure/clojure/data/xml/test_names.clj
@@ -47,3 +47,11 @@
   (are [node] (= (parse-str (emit-str node)) node)
     (element ::D/limit {::V/moo "gee"}
              (element ::D/nresults nil "100"))))
+
+(deftest test-reassign-prefix
+  (are [node reparsed] (= (parse-str (emit-str node)) reparsed)
+    (element ::D/limit {:xmlns/D "DAV:"}
+             ;; because of outer binding, "uri-v:" will be bound to
+             ;; generated xmlns:a instead of xmlns:D
+             (element ::V/other {:xmlns/D "uri-v:"}))
+    (element ::D/limit {} (element ::V/other))))


fixed renaming issue

fixed renaming issue

--- test/gorillalabs/tesla/component/health_test.clj
+++ test/gorillalabs/tesla/component/health_test.clj
@@ -1,4 +1,4 @@
-(ns gorillalabs.tesla.stateful.health-test
+(ns gorillalabs.tesla.component.health-test
   (:require [clojure.test :refer :all]
             [gorillalabs.tesla.component.health :as health]
             [gorillalabs.tesla :as system]


Removing repo from project.clj

Removing repo from project.clj

--- sherpa-clojure/project.clj
+++ sherpa-clojure/project.clj
@@ -21,8 +21,4 @@
   :target-dir "target"
   :compile-path "target/classes"

-  :omit-default-repositories true
-
-  :repositories {"rev-repo" {:url "https://build.knoodel.net/maven-repo/content/groups/public"
-                             :username "revelytix-deploy"
-                             :password "f9uUejDk"}})
+  :omit-default-repositories true)


New tests: test-properties->map-1/2

New tests: test-properties->map-1/2

--- test/emender_jenkins/config_loader_test.clj
+++ test/emender_jenkins/config_loader_test.clj
@@ -183,12 +183,13 @@
     (let [property (doto (new java.util.Properties)
                          (.setProperty "a" "A")
                          (.setProperty "b" "B"))]
-        (is (= {:a 'A :b 'B} (properties->map property)))))
+        (is (= {:a "A" :b "B"} (properties->map property)))))

 (deftest test-properties->map-2
     "Check the behaviour of function emender-jenkins/properties->map."
     (let [property (doto (new java.util.Properties)
                          (.setProperty "propertyA" "property_a")
                          (.setProperty "propertyB" "property_b"))]
-        (is (= {:propertyA 'property_a :propertyB 'property_b} (properties->map property)))))
+        (is (= {:propertyA "property_a" :propertyB "property_b"} (properties->map property)))))

+


making test work

making test work

--- code/test/code/core_test.clj
+++ code/test/code/core_test.clj
@@ -11,5 +11,10 @@

 (deftest word-count
   (let [input "txt/tom-sawyer.txt" output "result"]
-    (io/delete-file output true)
-    (is (tool-run (clojure_hadoop.job.) ["-i" input "-o" output ]))))
+    (delete-dir output)
+    (is (tool-run (clojure_hadoop.job.) ["-i" input "-o" output ]))
+    (take 4 (split-lines (slurp (str output "/part-r-00000"))))
+    ))
+
+
+


Better whitespace handling

Better whitespace handling

--- src/alfresco_technical_validation/impl/source_indexes.clj
+++ src/alfresco_technical_validation/impl/source_indexes.clj
@@ -57,7 +57,7 @@
         :stb11          #"(?:^|\s)catch(?:\s|$)"
       }
     :javascript {
-        :sec05          #"(?:^|\s)eval\("
+        :sec05          #"(?:^|\s)eval\s*\("
       }
     :web-script-descriptor {
         :stb19          #"<transaction>\s*none\s*</transaction>"
@@ -66,7 +66,7 @@
       }
     :spring-app-context {
         :api05          #"(?:^|\s)ref=\s*\"(?!ServiceRegistry)"
-        :stb15          #"parent=\"dictionaryModelBootstrap\""
+        :stb15          #"parent=\s*\"dictionaryModelBootstrap\""
       }
     :content-model {
         :perf02         #"<index\s+enabled\s*=\s*\"true"


up cpu limit per service from 2 to 4

up cpu limit per service from 2 to 4

--- src/cljs/swarmpit/component/service/form_resources.cljs
+++ src/cljs/swarmpit/component/service/form_resources.cljs
@@ -61,7 +61,7 @@
       (comp/slider
         {:key          "cpu-limit"
          :min          0
-         :max          2
+         :max          4
          :step         0.10
          :defaultValue 0
          :value        value
@@ -103,4 +103,4 @@
          :sm   6}
         (form/subsection "Limit")
         (form-memory-limit (:memory limit))
-        (form-cpu-limit (:cpu limit))))))+        (form-cpu-limit (:cpu limit))))))


(maint) Clarify logging around CRL updates

Previously the message that we were updating the CRL would get logged
even if an error occurred during processing that stopped any update from
actually being written to the CRL. This commit makes that initial
message less definitive and logs a separate message when the update
actually succeeded.

--- src/clj/puppetlabs/puppetserver/certificate_authority.clj
+++ src/clj/puppetlabs/puppetserver/certificate_authority.clj
@@ -1450,7 +1450,7 @@
                      "Received CRLs for issuer {0} but none were newer than the existing CRL; keeping the existing CRL."
                      issuer))
           (log/info (i18n/trs
-                     "Updated CRL for issuer {0}." issuer)))
+                     "Updating CRL for issuer {0}." issuer)))
         new-crl)
       ;; no new CRLs found for this issuer, keep it
       crl)))
@@ -1461,7 +1461,7 @@
   [incoming-crls :- [X509CRL]
    crl-path :- schema/Str
    cert-chain-path :- schema/Str]
-  (log/info (i18n/trs "Updating CRL at {0}" crl-path))
+  (log/info (i18n/trs "Processing update to CRL at {0}" crl-path))
   (let [current-crls (utils/pem->crls crl-path)
         cert-chain (utils/pem->certs cert-chain-path)
         ca-cert-key (utils/get-extension-value (first cert-chain)
@@ -1483,7 +1483,8 @@
         new-ext-crl-chain (cons ca-crl (map #(maybe-replace-crl % incoming-crls-by-key-id)
                                             external-crl-chain))]
     (validate-certs-and-crls cert-chain new-ext-crl-chain)
-    (write-crls new-ext-crl-chain crl-path)))
+    (write-crls new-ext-crl-chain crl-path)
+    (log/info (i18n/trs "Successfully updated CRL at {0}" crl-path))))

 (schema/defn ensure-directories-exist!
   "Create any directories used by the CA if they don't already exist."


memory monitoring

memory monitoring


don't use :replace in watch-spec; too many breakages

--- src/main/clojure/com/stuartsierra/lazytest/watch.clj
+++ src/main/clojure/com/stuartsierra/lazytest/watch.clj
@@ -81,7 +81,7 @@
     (apply watch-dir d
            (fn [names]
              (try
-              (when-let [results (run-spec names :replace)]
+              (when-let [results (run-spec names :reload)]
                 (reporter results))
               (catch Throwable t
                 (reporter (TestThrown names nil t)))))


Remove debug prints

Remove debug prints

--- src/nml/core.clj
+++ src/nml/core.clj
@@ -189,9 +189,7 @@
          :value identity
          :values (fn [& values] (into [] values))
          }]
-    (println (str "#PM# 0 " tree))
     (let [newtree (insta/transform transformers tree)]
-      (println (str "#PM# 1 " newtree))
       newtree)))

 ;;(defn nml-set [m nml key val]


:bug: Don't define constant on presence ns.


Relations  declare|parents-target|pattern and declare|parents-target|type.

--- EkekoAspectJ/src/damp/ekeko/aspectj/weaverworld.clj
+++ EkekoAspectJ/src/damp/ekeko/aspectj/weaverworld.clj
@@ -1221,8 +1221,6 @@
     (succeeds (instance? DeclareSoft ?declare))))

-
-
 (defn
   declare|parents-patterns
   "Relation between a declare parents ?declare and its TypePatternList of declared ?parents."
@@ -1231,19 +1229,53 @@
     (declare|parents ?declare)
     (equals ?parents (.getParents ?declare))))

+
 (comment
-(defn
-  declare|parents-pattern
-  "Relation between a declare parents ?declare and of its type patterns."
-  [?declare ?parent]
-  (fresh [?parents]
-         (declare|parents-patterns ?declare ?parents)
-         (contains ?parents ?parent)))
+
+; Commented out because isExtends is always true
+; TODO:if necessary to distinguish extends/implements declare parents, find other way
+
+; // note - will always return true after deserialization, this doesn't affect weaver
+;	public boolean isExtends() {
+;		return this.isExtends;
+;	}
+
+
+  (defn
+    declare|parents|extends
+    "Relation of declare parents extends declarations."
+    [?declare]
+    (all
+      (declare|parents ?declare)
+      (succeeds (.isExtends ?declare))))
+
 )
-
-
-
-
+
+
+
+(defn
+  declare|parents-target|pattern
+  "Relation between a declare parents declaration and its target type pattern."
+  [?declare ?targetpattern]
+  (all
+    (declare|parents ?declare)
+    (equals ?targetpattern (.getChild ?declare))))
+
+;;TODO: iterating over all types is slow, and might miss types that match dynamically:
+;; 	public boolean match(ResolvedType typeX) {
+;;		if (!child.matchesStatically(typeX)) {
+;;			return false;
+;;		}
+;; ....
+
+(defn
+  declare|parents-target|type
+  "Relation between a declare parents declaration and its target type."
+  [?declare ?target]
+  (all
+    (declare|parents ?declare)
+    (type ?target)
+    (succeeds (.match ?declare ?target))))

 (defn


Make Cook not fail silently on startup on some startup errors.

--- scheduler/src/cook/config.clj
+++ scheduler/src/cook/config.clj
@@ -76,7 +76,7 @@
                :level default}
               overrides))
      (catch Throwable t
-       (.println System/err "Failed to initialize logging!")
+       (.println System/err (str "Failed to initialize logging! Error: " (.toString t)))
        (stacktrace/print-cause-trace t)
        (throw t)))))


fixing formatting

fixing formatting

--- src/qu/cache.clj
+++ src/qu/cache.clj
@@ -81,7 +81,7 @@
        (let [collection (query-to-key query)]
          (if (coll/exists? collection)
            (do (log/info "FOUND Aggregation - ID:" collection)
-			(metrics/increment "cache.hit.count")
+            (metrics/increment "cache.hit.count")
              (extract-result collection query))
            (do (metrics/increment "cache.wait.count")
                not-found))))))


add producer and asyn client

add producer and asyn client

--- kafka-clj/src/kafka_clj/produce3.clj
+++ kafka-clj/src/kafka_clj/produce3.clj
@@ -1,12 +1,27 @@
 (ns kafka-clj.produce3
-  (:require [kafka-clj.codec :refer [crc32-int get-compress-out compress]])
-  (:import [java.nio ByteBuffer]
+  (:require [kafka-clj.codec :refer [crc32-int get-compress-out compress]]
+            [clj-tcp.client :refer [client write!]])
+  (:import [java.net InetAddress]
+           [java.nio ByteBuffer]
            [io.netty.buffer ByteBuf Unpooled]
            [java.nio.channels SocketChannel]
            [java.net InetSocketAddress]
            [kafka_clj.util Util]))

+(defrecord Producer [client host port])
+
+(defonce ^:constant API_KEY_PRODUCE_REQUEST (short 0))
+(defonce ^:constant API_VERSION (short 0))
+
+(defonce ^:constant MAGIC_BYTE (int 0))
 (defonce ^:constant compression-code-mask 0x03)
+
+(defn ^ByteBuf inc-capacity [^ByteBuf bytebuf l]
+  (let [len (+ (.capacity bytebuf) (int l))]
+    (if (> len (.maxCapacity bytebuf))
+      (.capacity bytebuf len))
+    bytebuf))
+

 (defn put-short-string [^ByteBuf buff s]
   (-> buff
@@ -64,14 +79,15 @@
 	        )))))

-(defn write-request [^ByteBuf buff codec msgs]
+(defn write-request [^ByteBuf buff {:keys [correlation-id client-id codec acks timeout] :or {correlation-id 1 client-id "1" codec 0 acks 1 timeout 1000}}
+                     msgs]
     (-> buff
-      (.writeShort (short 0))   ;api-key
-      (.writeShort (short 0))   ;version api
-      (.writeInt (int 1))       ;correlation id
-      (put-short-string "cid")  ;short + client-id bytes
-      (.writeShort (short 1))   ;acks
-      (.writeInt (int 1000)))    ;timeout
+      (.writeShort  (short API_KEY_PRODUCE_REQUEST))   ;api-key
+      (.writeShort  (short API_VERSION))   ;version api
+      (.writeInt (int correlation-id))       ;correlation id
+      (put-short-string client-id)  ;short + client-id bytes
+      (.writeShort (short acks))   ;acks
+      (.writeInt (int timeout)))    ;timeout

       (let [topic-group (group-by :topic msgs)]
         (.writeInt buff (int (count topic-group))) ;topic count
@@ -89,19 +105,17 @@
       )

+(defn send-messages [{:keys [client]}
+                     conf
+                     msgs]
+  (write! client (fn [^ByteBuf buff]
+                   (with-size buff write-request conf msgs)
+                   )))

-(defn send-msg [topic partition codec msgs]
+
+(defn producer [host port]
   (try
-		  (let [
-		        buff (with-size (Unpooled/buffer 1024) write-request codec msgs)
-
-		        read-buff (ByteBuffer/allocate 1024)
-		        ch (SocketChannel/open (InetSocketAddress. "localhost" (int 9092)))
-		        write-int (.write ch (.nioBuffer buff))
-		        read-int (try (.read ch read-buff) (catch Exception e (do (prn e) -1)))
-		        ]
-		    (prn "Read int " read-int)
-		    (prn (java.util.Arrays/toString (-> read-buff .array)))
-		    )
-    (catch Exception e (.printStackTrace e))))
-
+  (let [c (client host port {:reuse-client true})]
+    (->Producer c host port))
+  (catch Exception e (.printStackTrace e))))
+


CMD-S pressed again when saved exits edit mode

--- iwaswhere-web/src/cljs/iwaswhere_web/markdown.cljs
+++ iwaswhere-web/src/cljs/iwaswhere_web/markdown.cljs
@@ -49,7 +49,13 @@
         on-keydown-fn (fn [ev] (let [key-code (.. ev -keyCode)
                                      meta-key (.. ev -metaKey)]
                                  (when (and meta-key (= key-code 83))
-                                   (put-fn [:text-entry/update temp-entry])
+                                   (if (not= entry temp-entry) ; when no change, toggle edit mode
+                                     (put-fn [:text-entry/update temp-entry])
+                                     (put-fn [:cmd/toggle {:timestamp ts :key :show-edit-for}]))
+                                   (.preventDefault ev))
+                                 (when (= key-code 9)
+                                   ;(put-fn [:text-entry/update temp-entry])
+                                   (prn key-code)
                                    (.preventDefault ev))))]
     [:div.edit-md
      [:pre [:code {:content-editable true


Remove unused core test

Remove unused core test

--- worker/test/worker/core_test.clj
+++ worker/test/worker/core_test.clj
@@ -1,7 +0,0 @@
-(ns worker.core-test
-  (:use clojure.test
-        worker.core))
-
-(deftest a-test
-  (testing "FIXME, I fail."
-    (is (= 0 1))))


fix filtering

fix filtering

--- labs/architecture-examples/om/src/todomvc/app.cljs
+++ labs/architecture-examples/om/src/todomvc/app.cljs
@@ -21,8 +21,9 @@
 ;; =============================================================================
 ;; Routing

-(defroute "/:filter" [filter]
-  (swap! app-state assoc :showing (keyword filter)))
+(defroute "/" [] (swap! app-state assoc :showing :all))
+
+(defroute "/:filter" [filter] (swap! app-state assoc :showing (keyword filter)))

 (def history (History.))


Restrict access to /api/projects, /api/actions only to authenticated users.

--- web-server/src/clj/hatnik/web/server/handler.clj
+++ web-server/src/clj/hatnik/web/server/handler.clj
@@ -39,11 +39,22 @@
    {:result :ok
     :version "1.6.0"}))

+(defn wrap-authenticated-only [handler]
+  (fn [req]
+    (if (-> req :session :user)
+      (handler req)
+      (do (timbre/debug "Unauthorized request")
+          {:status 401
+           :body {:result "error"
+                  :message "Not authenticated"}}))))
+
 (defroutes app-routes
   (GET "/" [] renderer/core-page)
   (context "/api" []
-           (context "/projects" [] projects-api)
-           (context "/actions" [] actions-api)
+           (context "/projects" []
+                    (wrap-authenticated-only projects-api))
+           (context "/actions" []
+                    (wrap-authenticated-only actions-api))
            login-api
            (GET "/library-version" [group artifact] (library-version group artifact)))
   (route/resources "/")


Clean up some problematic temporary load-time code

--- src/afterglow/examples.clj
+++ src/afterglow/examples.clj
@@ -144,8 +144,10 @@
              (params/build-variable-param :pan)
              (afterglow.channels/extract-channels (show/fixtures-named :blade) #(= (:type %) :pan))))

-(show/add-midi-control-to-var-mapping "Slider" 0 4 :tilt :max 255.99)
-(show/add-midi-control-to-var-mapping "Slider" 0 20 :pan :max 255.99)
+(defn add-pan-tilt-controls
+  []
+  (show/add-midi-control-to-var-mapping "Slider" 0 4 :tilt :max 255.99)
+  (show/add-midi-control-to-var-mapping "Slider" 0 20 :pan :max 255.99))

 (require '(afterglow [transform :as transform]))
 (defn test-position


Add torrent motor reset cue.

Add torrent motor reset cue.

--- src/afterglow/examples.clj
+++ src/afterglow/examples.clj
@@ -601,6 +601,9 @@
     ;; The upper page of torrent config cues
     (ct/set-cue! (:cue-grid *show*) 0 15
                  (cues/function-cue :torrent-shutter :shutter-open (show/fixtures-named "torrent")))
+    (ct/set-cue! (:cue-grid *show*) 1 15
+                 (cues/function-cue :torrent-reset :motor-reset (show/fixtures-named "torrent")
+                                    :color (create-color :red) :held true))

     (ct/set-cue! (:cue-grid *show*) 6 15
                  (cues/function-cue :t1-focus :focus (show/fixtures-named "torrent-1") :effect-name "Torrent 1 Focus"


Update oss.clj

Update oss.clj

--- src/aliyun_oss_clj/oss.clj
+++ src/aliyun_oss_clj/oss.clj
@@ -50,7 +50,7 @@
     )
   )

-;; (upload-file bucketName "README.md")
+;; (upload-file ossClient bucketName "README.md")
 (defn upload-file
   [ossClient bucket-name file-name]
   (.putObject ossClient bucket-name file-name (File. file-name))


test-org-settings require cleanup

test-org-settings require cleanup

--- test-cljs/frontend/components/test_org_settings.cljs
+++ test-cljs/frontend/components/test_org_settings.cljs
@@ -1,14 +1,7 @@
 (ns frontend.components.test-org-settings
-  (:require [cljs.core.async :as async]
-            [frontend.test-utils :as test-utils :refer [example-plan is-re]]
+  (:require [frontend.test-utils :as test-utils :refer [example-plan is-re]]
             [frontend.components.org-settings :as org-settings]
-            [frontend.utils.docs :as doc-utils]
             [frontend.utils.html :refer [hiccup->html-str]]
-            [frontend.stefon :as stefon]
-            [goog.dom]
-            [om.core :as om :include-macros true]
-            [frontend.routes :as routes]
-            [om.dom :refer (render-to-str)]
             [cljs.test :as test :refer-macros [deftest is testing]]))

 (deftest test-discount-rendering


(PDB-5216) query-logging-test: rework ns form before before changes

Fix the ns form indentation and ordering in advance of a number of
changes that will require altering most of the lines anyway.

--- test/puppetlabs/puppetdb/http/query_logging_test.clj
+++ test/puppetlabs/puppetdb/http/query_logging_test.clj
@@ -1,16 +1,16 @@
 (ns puppetlabs.puppetdb.http.query-logging-test
-  (:require  [clojure.test :refer :all]
-             [clojure.string :as str]
-             [puppetlabs.kitchensink.core :as kitchensink]
-             [puppetlabs.puppetdb.testutils.http :refer [query-response]]
-             [puppetlabs.puppetdb.testutils.db :refer [with-test-db *db*]]
-             [puppetlabs.puppetdb.testutils.http :refer [call-with-http-app]]
-             [puppetlabs.puppetdb.testutils.services :refer [call-with-puppetdb-instance
-                                                             create-temp-config
-                                                             *server*]]
-             [puppetlabs.puppetdb.cli.services :as svcs]
-             [puppetlabs.trapperkeeper.app :refer [get-service]]
-             [puppetlabs.trapperkeeper.testutils.logging :as tk-log]))
+  (:require
+   [clojure.string :as str]
+   [clojure.test :refer :all]
+   [puppetlabs.kitchensink.core :as kitchensink]
+   [puppetlabs.puppetdb.cli.services :as svcs]
+   [puppetlabs.puppetdb.testutils.db :refer [with-test-db *db*]]
+   [puppetlabs.puppetdb.testutils.http
+    :refer [call-with-http-app query-response]]
+   [puppetlabs.puppetdb.testutils.services
+    :refer [call-with-puppetdb-instance create-temp-config *server*]]
+   [puppetlabs.trapperkeeper.app :refer [get-service]]
+   [puppetlabs.trapperkeeper.testutils.logging :as tk-log]))

 (defn logs-include?
   "Returns true if only one instance of unique-msg is found in the log."


more work on docs site

more work on docs site

--- docs/src/cljs/om_bootstrap/docs.cljs
+++ docs/src/cljs/om_bootstrap/docs.cljs
@@ -22,7 +22,6 @@

 (defn button-sizing []
   (d/div
-   {}
    (b/toolbar {}
               (b/button {:bs-style "primary" :bs-size "large"} "Large button")
               (b/button {:bs-size "large"} "Large button"))
@@ -37,33 +36,86 @@
                         "Extra small button")
               (b/button {:bs-size "large"} "Large button"))))

+(defn button-block []
+  (d/div
+   (d/h3 "Button Examples")
+   (button-example)
+   (d/h3 "Button Sizing")
+   (button-sizing)
+   (d/p "Create block level buttons—those that span the full width of a parent— by adding the block prop.")
+   (d/div {:class "well"
+           :style {:max-width 400
+                   :margin "0 auto 10px"}}
+          (b/button {:bs-style "primary" :bs-size "large" :block? true}
+                    "Block level button")
+          (b/button {:bs-size "large" :block? true}
+                    "Block level button"))
+   (d/p "To set a buttons active state simply set the components active prop.")
+   (b/toolbar {}
+              (b/button {:bs-style "primary" :bs-size "large" :active? true}
+                        "Primary button")
+              (b/button {:bs-size "large" :bs-style "default" :active? true}
+                        "Button"))
+   (d/p "Make buttons look unclickable by fading them back 50%. To do
+   this add the disabled attribute to buttons.")
+   (b/toolbar {}
+              (b/button {:bs-style "primary" :bs-size "large" :disabled? true}
+                        "Primary button")
+              (b/button {:bs-size "large" :bs-style "default" :disabled? true}
+                        "Button"))
+   (d/h3 "Button Groups")
+   (d/p "Wrap a series of buttons in a button group.")
+   (b/button-group {}
+                   (b/button {} "Left")
+                   (b/button {} "Middle")
+                   (b/button {} "Right"))
+   (d/p "Combine sets of buttongroups into a button toolbar for more
+   complex components.")
+   (b/toolbar {}
+              (b/button-group {} (for [i (range 4)]
+                                   (b/button {} (str (inc i)))))
+              (b/button-group {} (for [i (range 4 7)]
+                                   (b/button {} (str (inc i)))))
+              (b/button-group {} (b/button {} 8)))
+
+   (d/p "Instead of applying button sizing props to every button in a group, just add bs-size prop to the <ButtonGroup />.")
+   (let [buttons (for [s ["Left" "Middle" "Right"]]
+                   (b/button {} s))]
+     (b/toolbar {}
+                (b/toolbar {} (b/button-group {:bs-size "large"} buttons))
+                (b/toolbar {} (b/button-group {} buttons))
+                (b/toolbar {} (b/button-group {:bs-size "small"} buttons))
+                (b/toolbar {} (b/button-group {:bs-size "xsmall"} buttons))))
+
+   ))
+
 ;; ## Jumbotron Examples

 (defn jumbotron-example []
   (r/jumbotron {}
-               (d/h1 {} "Hello, World!")
+               (d/h1 "Hello, World!")
                (d/p "This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.")
-               (d/p {} (b/button {:bs-style "primary"} "Learn More"))))
+               (d/p (b/button {:bs-style "primary"} "Learn More"))))

 ;; ## Label Examples

 (defn label-examples []
-  (d/div {}
-         (d/h1 {} "Label " (r/label {} "New"))
-         (d/h2 {} "Label " (r/label {} "New"))
-         (d/h3 {} "Label " (r/label {} "New"))
-         (d/h4 {} "Label " (r/label {} "New"))
-         (d/h5 {} "Label " (r/label {} "New"))
-         (d/p {} "Label " (r/label {} "New"))))
+  (d/div
+   (d/h1 "Label " (r/label {} "New"))
+   (d/h2 "Label " (r/label {} "New"))
+   (d/h3 "Label " (r/label {} "New"))
+   (d/h4 "Label " (r/label {} "New"))
+   (d/h5 "Label " (r/label {} "New"))
+   (d/p "Label " (r/label {} "New"))))

 (defn label-variations []
-  (d/div {}
-         (r/label {:bs-style "default"} "Default")
-         (r/label {:bs-style "primary"} "Primary")
-         (r/label {:bs-style "success"} "Success")
-         (r/label {:bs-style "info"} "Info")
-         (r/label {:bs-style "warning"} "Warning")
-         (r/label {:bs-style "danger"} "Danger")))
+  (d/div
+   (r/label {:bs-style "default"} "Default")
+   (r/label {:bs-style "primary"} "Primary")
+   (r/label {:bs-style "success"} "Success")
+   (r/label {:bs-style "info"} "Info")
+   (r/label {:bs-style "warning"} "Warning")
+   (r/label {:bs-style "danger"} "Danger")))

 ;; ## Well Examples

@@ -71,15 +123,15 @@
     (r/well {} "Look, I'm in a well!"))

 (def optional-well-classes
-  (d/div {}
-         (r/well {:bs-size "large"} "Look, I'm in a large well!")
-         (r/well {:bs-size "small"} "Look, I'm in a small well!")))
+  (d/div
+   (r/well {:bs-size "large"} "Look, I'm in a large well!")
+   (r/well {:bs-size "small"} "Look, I'm in a small well!")))

 ;; ## Page Header

 (def header-example
   (r/page-header {} "Example page header "
-                 (d/small {} "Subtext for header")))
+                 (d/small "Subtext for header")))

 ;; ## Grid

@@ -109,63 +161,31 @@
                         (g/col {:md 6 :md-pull 6}
                                (d/code {} "(g/col {:md 6 :md-push 6})"))))))

-;; ## Final Page Loading
-
-(defcomponentk app
-  "This is the top level component that renders the entire example
-  docs page."
-  []
-  (render [_]
-          (d/div {}
-                 (d/h3 {} "Button Examples")
-                 (button-example)
-                 (d/h3 {} "Button Sizing")
-                 (button-sizing)
-                 (d/h3 {} "Jumbotron")
-                 (jumbotron-example)
-                 (d/h3 {} "Label Examples")
-                 (label-examples)
-                 (d/h3 {} "Label Variations")
-                 (label-variations)
-                 (d/h3 {} "Well!")
-                 default-well
-                 optional-well-classes
-                 (d/h3 {} "Page Header")
-                 header-example
-                 (d/h3 {} "Grid")
-                 grid-example)))
-
-(defonce app-state
-  (atom {:text "Hi!"}))
-
-(om/root app app-state
-         {:target (. js/document (getElementById "app"))})
-
-(when-not (ws-repl/alive?)
-  (ws-repl/connect "ws://localhost:9001" :verbose true))
-
 ;; ## Tooltip

+(def tooltip-example
+  (d/div {:class "bs-example"}
+         (d/div {:style {:height 50}}
+                (r/tooltip {:placement "right"
+                            :position-left 150
+                            :position-top 50}
+                           (d/strong "Holy guacamole!")
+                           "Check this info."))))
+
 (comment
-  "Tooltip component:"
-  (d/div {:style {:height 50}}
-         (t/tooltip {:placement "right"
-                     :position-left 150
-                     :position-top 50}
-                    (d/strong "Holy guacamole!")
-                    "Check this info."))
-
-  "Positioned tooltip component. (TODO: Needs overlay trigger to finish!)"
-  (let [tooltip  (r/tooltip {}
-                            (d/strong "Holy guacamole!")
-                            "Check this info.")]
-    (b/toolbar {}
-               (overlay-trigger {:placement "left" :overlay tooltip})
-               (overlay-trigger {:placement "top" :overlay tooltip})
-               (overlay-trigger {:placement "bottom" :overlay tooltip})
-               (overlay-trigger {:placement "right" :overlay tooltip})))
-
-  "Positioned tooltip in copy. (TODO: Needs overlay trigger to finish!)"
+
+  (def positioned-tooltip-example
+    "Positioned tooltip component. (TODO: Needs overlay trigger to
+   finish!)"
+    (let [tooltip  (r/tooltip {}
+                              (d/strong "Holy guacamole!")
+                              "Check this info.")]
+      (b/toolbar {}
+                 (overlay-trigger {:placement "left" :overlay tooltip})
+                 (overlay-trigger {:placement "top" :overlay tooltip})
+                 (overlay-trigger {:placement "bottom" :overlay tooltip})
+                 (overlay-trigger {:placement "right" :overlay tooltip}))))
+
   (defn link-with-tooltip
     [{:keys [tooltip href]} & children]
     (overlay-trigger {:placement "top"
@@ -174,31 +194,69 @@
                       :delay-hide 150}
                      (d/a {:href href} children)))

-  (d/p {:class "muted" :style {:margin-bottom 0}}
-       "Call me Ishmael. Some years ago - never mind how long "
-       (link-with-tooltip {:tooltip "Probably about two." :href "#"} "precisely")
-       " - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly "
-       (link-with-tooltip {:tooltip "The eleventh month!" :href "#"} "November")
-       " in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the "
-       (link-with-tooltip {:tooltip "A large alley or a small avenue." :href "#"} "street")
-       "m and methodically knocking people's hats off - then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in "
-       (link-with-tooltip {:tooltip "The ship, that is." :href "#"} "this")
-       ". If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me."))
+  (def positioned-tooltip-with-copy
+    (d/p {:class "muted" :style {:margin-bottom 0}}
+         "Call me Ishmael. Some years ago - never mind how long "
+         (link-with-tooltip {:tooltip "Probably about two." :href "#"} "precisely")
+         " - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly "
+         (link-with-tooltip {:tooltip "The eleventh month!" :href "#"} "November")
+         " in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the "
+         (link-with-tooltip {:tooltip "A large alley or a small avenue." :href "#"} "street")
+         "m and methodically knocking people's hats off - then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in "
+         (link-with-tooltip {:tooltip "The ship, that is." :href "#"} "this")
+         ". If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.")))

 ;; ## Alerts

-(comment
-  "Alert component."
-
+(def alert-example
   "Basic alert styles:"
   (r/alert {:bs-style "warning"}
            (d/strong "Holy guacamole!")
-           "Best check yo self, you're not looking too good.")
-
-  "Closeable alerts, just pass in a onDismiss function."
+           "Best check yo self, you're not looking too good."))
+
+(comment
+  "TODO: Closeable alerts, just pass in a onDismiss function."
   ;; Fill in.

-  "Auto close after a set time with dismissAfter prop."
+  "TODO: Auto close after a set time with dismissAfter prop."
   ;; Fill in.
-
   )
+;; ## Final Page Loading
+
+(defcomponentk app
+  "This is the top level component that renders the entire example
+  docs page."
+  []
+  (render [_]
+          (d/div
+           (button-block)
+           (d/h3 "Jumbotron")
+           (jumbotron-example)
+           (d/h3 "Label Examples")
+           (label-examples)
+           (d/h3 "Label Variations")
+           (label-variations)
+           (d/h3 "Well!")
+           default-well
+           optional-well-classes
+           (d/h3 "Page Header")
+           header-example
+           (d/h3 "Grid")
+           grid-example
+           (d/h3 "Tooltip")
+           tooltip-example
+           (d/h3 "Positioned Tooltip (in progress)")
+           (d/h3 "Alert")
+           alert-example)))
+
+(defonce app-state
+  (atom {:text "Hi!"}))
+
+(defn load-om []
+  (om/root app app-state
+           {:target (. js/document (getElementById "app"))}))
+
+(load-om)
+
+(when-not (ws-repl/alive?)
+  (ws-repl/connect "ws://localhost:9001" :verbose true))


fix spaces

fix spaces

--- docs/src/cljs/om_bootstrap/docs.cljs
+++ docs/src/cljs/om_bootstrap/docs.cljs
@@ -286,7 +286,7 @@
 (defn progress-bar-block []
   (section
    "progress"
-   ["Progress bars" (d/small "ProgressBar")]
+   ["Progress bars " (d/small "ProgressBar")]
    (d/p {:class "lead"}
         "Provide up-to-date feedback on the progress of a workflow or
         action with simple yet flexible progress bars.")
@@ -329,7 +329,7 @@
 (defn nav-block []
   (section
    "navs"
-   ["Navs" (d/small "Nav, NavItem")]
+   ["Navs " (d/small "Nav, NavItem")]
    (d/h3 "Example navs")
    (d/p "Navs come in two styles, pills:")
    (->example (slurp-example "nav/pills"))
@@ -342,7 +342,7 @@
 (defn navbar-block []
   (section
    "navbars"
-   ["Navbars" (d/small "Navbar, Nav, NavItem")]
+   ["Navbars " (d/small "Navbar, Nav, NavItem")]
    (d/h3 "Example navbars")
    (TODO)))

@@ -351,7 +351,7 @@
 (defn tab-block []
   (section
    "tabs"
-   ["Toggleable tabs" (d/small "TabbedArea, TabPane")]
+   ["Toggleable tabs " (d/small "TabbedArea, TabPane")]
    (d/h2 "Example tabs")
    (d/p "Add quick, dynamic tab functionality to transition through
    panes of local content, even via dropdown menus.")
@@ -379,7 +379,7 @@
 (defn pager-block []
   (section
    "pager"
-   ["Pager" (d/small "Pager, PageItem")]
+   ["Pager " (d/small "Pager, PageItem")]
    (d/p "Quick previous and next links.")
    (d/h3 "Default")
    (d/p "Centers by default.")
@@ -403,7 +403,7 @@
 (defn alert-block []
   (section
    "alerts"
-   ["Alert messages" (d/small "Alert")]
+   ["Alert messages " (d/small "Alert")]
    (d/h3 "Example alerts")
    (d/p "Basic alert styles.")
    (->example (slurp-example "alert/basic"))
@@ -421,7 +421,7 @@
 (defn carousel-block []
   (section
    "carousels"
-   ["Carousels" (d/small "Carousel, CarouselItem")]
+   ["Carousels " (d/small "Carousel, CarouselItem")]
    (d/h2 "Example Carousels")
    (d/h3 "Uncontrolled")
    (d/p "Allow the component to control its own state.")
@@ -436,7 +436,7 @@
 (defn grid-block []
   (section
    "grids"
-   ["Grids" (d/small "Grid, Row, Col")]
+   ["Grids " (d/small "Grid, Row, Col")]
    (d/h3 "Example grids")
    (->example (slurp-example "grid"))))


Handle case in which input's type is char


Added opaque-id to the examples for easier tracking.


Minor ws changes

Minor ws changes


compilation fixes

compilation fixes


maps should be maps

maps should be maps

--- src/bardo/interpolate.cljx
+++ src/bardo/interpolate.cljx
@@ -47,7 +47,7 @@
   (if (every? sequential? [x y])
     (match (mapv counted? [x y])
            [false false] (throw
-                        (#+cljs js/Exception #+clj #+cljs js/Exception #+clj Exception. "Cannot interpolate between two uncounted sequences"))
+                        (#+cljs js/Error #+clj #+cljs js/Exception #+clj Exception. "Cannot interpolate between two uncounted sequences"))
            [false _] [(take (count y) x) y]
            [_ false] [x (take (count x) y)]
            [_ _] [x y])
@@ -65,7 +65,7 @@
   (when (or (apply f s)
             (apply f (reverse s)))
     (throw
-     (#+cljs js/Exception #+clj Exception. msg))))
+     (#+cljs js/Error #+clj Exception. msg))))

 (defn pair-pred [pred]
   (comp (partial every? identity)
@@ -124,7 +124,7 @@
   #+cljs PersistentArrayMap
   (-interpolate [start end]
     (fn [t]
-      (seq (for [k (->> [start end]
+      (into {} (for [k (->> [start end]
                         (map keys)
                         (map set)
                         (apply union))]
@@ -143,7 +143,7 @@
         ((apply wrap-size wrapped) (apply -interpolate wrapped))
         (do
           (throw
-           (#+cljs js/Exception #+clj Exception. (str "Cannot interpolate between " start " and " end))))))))
+           (#+cljs js/Error #+clj Exception. (str "Cannot interpolate between " start " and " end))))))))

 (defn mix
   [start end]


accompanying_material has been renamed

accompanying_material has been renamed

using dashes instead of underscore

--- src/catalog/validation.clj
+++ src/catalog/validation.clj
@@ -39,7 +39,7 @@
     :library-signature LibrarySignature
     (s/optional-key :product-number) LibrarySignature
     (s/optional-key :price) s/Str
-    (s/optional-key :accompanying_material) s/Str
+    (s/optional-key :accompanying-material) s/Str
     (s/optional-key :language) Language
     }))


replacing :errors with :message

replacing :errors with :message

--- src/celestial/api/jobs.clj
+++ src/celestial/api/jobs.clj
@@ -39,9 +39,9 @@
   ([id action msg args]
     (cond
       (not (s/system-exists? id))
-        (bad-req {:errors (<< "No system found with given id ~{id}")})
+        (bad-req {:message (<< "No system found with given id ~{id}")})
       (not (u/op-allowed? action (current-user)))
-        (bad-req {:errors (<< "Operation ~{action} not allowed for user ~(current-user)")})
+        (bad-req {:message (<< "Operation ~{action} not allowed for user ~(current-user)")})
       :else
        (let [m {:identity id :args args :tid (get-tid)
                :env (s/get-system id :env) :user (current-user)}]


cleanup

cleanup

--- src/ceres_collector/db.clj
+++ src/ceres_collector/db.clj
@@ -178,15 +178,7 @@
   [{:keys [url content-type ts] :as expanded-url} url-id]
   (let [raw-html (if (= url :not-available)
                    nil
-                   (slurp url))
-       html-title (if raw-html
-                     (-> (java.io.StringReader. raw-html)
-                         enlive/html-resource
-                         (enlive/select [:head :title])
-                         first
-                         :content
-                         first)
-                     :not-available)]
+                   (slurp url))]
     (mc/insert-and-return
      @db
      "htmls"


Remove unnecessary arrow.

Remove unnecessary arrow.

--- src/circle/backend/git.clj
+++ src/circle/backend/git.clj
@@ -149,18 +149,17 @@
   "Returns a map of important commit information"
   [repo commit]
   (let [f #(format-log repo commit %)]
-    (->
-     ;; In the order of the git-log man page
-     {:parents (-> :P f (split #" "))
-      :author_name (f :an)
-      :author_email (f :ae)
-      :author_date (f :at)
-      :committer_name (f :cn)
-      :committer_email (f :ce)
-      :committer_date (f :ct)
-      :subject (f :s)
-      :body (f :b)
-      :branch (name-rev repo commit)})))
+    ;; In the order of the git-log man page
+    {:parents (-> :P f (split #" "))
+     :author_name (f :an)
+     :author_email (f :ae)
+     :author_date (f :at)
+     :committer_name (f :cn)
+     :committer_email (f :ce)
+     :committer_date (f :ct)
+     :subject (f :s)
+     :body (f :b)
+     :branch (name-rev repo commit)}))

 (defn latest-remote-commit
   "Returns the most recent on origin/master. Does not fetch."


Node.js REPL wip

Node.js REPL wip

--- src/clj/cljs/repl/node.clj
+++ src/clj/cljs/repl/node.clj
@@ -19,9 +19,6 @@
            java.net.Socket
            java.lang.StringBuilder
            [java.io BufferedReader BufferedWriter]))
-
-(def current-repl-env (atom nil))
-(def loaded-libs (atom #{}))

 (defn socket [host port]
   (let [socket (Socket. host port)
@@ -51,18 +48,18 @@
                (.append sb (char c))
                (recur sb (.read in)))))))

-(defn node-eval [{:keys [in out]} js]
+(defn node-eval [{{:keys [in out]} :socket :as repl-env} js]
   (write out js)
   {:status :success :value (read-response in)})

-(defn load-javascript [ctx ns url]
-  (node-eval ctx (slurp url)))
+(defn load-javascript [repl-env ns url]
+  (node-eval repl-env (slurp url)))

 (defn setup [repl-env]
   (let [env   (ana/empty-env)
         scope (:scope repl-env)]
     (repl/load-file repl-env "cljs/core.cljs")
-    (swap! loaded-libs conj "cljs.core")
+    (swap! (:loaded-libs repl-env) conj "cljs.core")
     (repl/evaluate-form repl-env
       env "<cljs repl>"
       '(ns cljs.user))
@@ -70,18 +67,20 @@
       env "<cljs repl>"
       '(set! *print-fn* (fn [x] (js/node_repl_print (pr-str x)))))))

-(extend-protocol repl/IJavaScriptEnv
-  clojure.lang.IPersistentMap
-  (-setup [this] (setup this))
-  (-evaluate [this filename line js] (node-eval this js))
-  (-load [this ns url] (load-javascript this ns url))
-  (-tear-down [this] (close-socket this)))
-
-;; do we need to implement our own version of goog.require ? - David
+(defrecord NodeEnv [socket loaded-libs]
+  repl/IJavaScriptEnv
+  (-setup [this]
+    (setup this))
+  (-evaluate [this filename line js]
+    (node-eval this js))
+  (-load [this ns url]
+    (load-javascript this ns url))
+  (-tear-down [this]
+    (close-socket socket)))

 (defn repl-env
   [& {:keys [host port] :or {host "localhost" port 5001}}]
-  (let [repl-env (socket host port)
+  (let [repl-env (NodeEnv. (socket host port) (atom {}))
         base     (io/resource "goog/base.js")
         deps     (io/resource "goog/deps.js")]
     (node-eval repl-env (slurp (io/reader base)))


Get user profile (or at least what's useful from it)

--- src/clj/skytwit/server.clj
+++ src/clj/skytwit/server.clj
@@ -87,10 +87,8 @@
 (chsk-send! 1 [:a/ping "hello"])
 )

-(comment
-
-  (def creds (get-credentials-from-env))
-
+(defn get-user-profile
+  [creds screen-name]
   (try
     (let [user (-> (tr/users-show :oauth-creds creds
                                   :params {:screen-name "InternetRadio"})
@@ -98,20 +96,7 @@
       {:name (:screen_name user)
        :number-of-tweets (:statuses_count user)
        :last-tweet-id (-> user :status :id)})
-    (catch Exception _ nil))
-  {:name "InternetRadio",
-   :number-of-tweets 3787133,
-   :last-tweet-id 696388911019462656}
-
-  (->> (tr/statuses-user-timeline :oauth-creds creds
-                                  :params {:screen-name "InternetRadio"
-                                           :max-id 696388911019462656
-                                           :trim-user true
-                                           :exclude-replies true
-                                           :count 200})
-      :body (map :id))
-
-  )
+    (catch Exception _ nil)))

 (defn get-tweets-before-tweet-id
   [creds screen-name id]


cleanup agent

cleanup agent

--- src/clj/swarmpit/agent.clj
+++ src/clj/swarmpit/agent.clj
@@ -13,21 +13,19 @@
     (doseq [service services]
       (let [id (:id service)
             repository (:repository service)]
-        (log/info repository)
         (try
           (let [current-digest (:imageDigest repository)
-                latest-digest (api/repository-digest nil (:name repository) (:tag repository))]
+                latest-digest (api/repository-digest nil
+                                                     (:name repository)
+                                                     (:tag repository))]
             (when (not= current-digest
                         latest-digest)
               (api/redeploy-service nil id)
-              (log/info "Service" id "has been redeployed! [" current-digest "] -> [" latest-digest "]")))
+              (log/info "Service" id "autoredeploy fired! DIGEST: [" current-digest "] -> [" latest-digest "]")))
           (catch ExceptionInfo e
             (log/error "Service" id "autoredeploy failed! " (dissoc (ex-data e) :headers))))))))

 (defn init []
   (schedule-task 60000
-                 (try
-                   (autoredeploy-job)
-                   (catch Exception ex
-                     (log/error "Autoredeploy execution failure:" ex)))
+                 (autoredeploy-job)
                  (init)))


Solve link mangling issue

Solve link mangling issue

See https://app.asana.com/0/17212341701456/161916714037564 for details,
seems to be either a new requirement on markdown-clj or a bug. I've
contacted Dmitri for details.

--- src/cljs/memento/core.cljs
+++ src/cljs/memento/core.cljs
@@ -64,7 +64,9 @@
    transformers/superscript
    transformers/blockquote
    paragraph-on-single-line                                 ; Replaces transformers/paragraph
-   transformers/br])
+   transformers/br
+   mdcommon/thaw-strings
+   ])

 (adapt-bootstrap OverlayTrigger)


Sort nested maps by key name alphabetically

--- src/cljs/praline/core.cljs
+++ src/cljs/praline/core.cljs
@@ -36,7 +36,7 @@
       [:div.row.gutter
        [:div.grid.twelve
         [:div.parent {:on-click (handle-show-path child-paths app-state)} label]
-        (for [[k v] this
+        (for [[k v] (sort-by (comp name first) (seq this))
               :when (some #{(conj key-path k)} visible)]
           ^{:key k}
           [inspect v (name k) (conj key-path k) app-state state])]])))
@@ -49,7 +49,7 @@
       [:div.row.gutter
        [:div.grid.twelve
         [:div.parent {:on-click (handle-show-path child-paths app-state)} label]
-        (for [[k v] this
+        (for [[k v] (sort-by (comp name first) (seq this))
               :when (some #{(conj key-path k)} visible)]
           ^{:key k}
           [inspect v (name k) (conj key-path k) app-state state])]])))


display only the basename of the path

display only the basename of the path

--- src/cljs/smgui/search.cljs
+++ src/cljs/smgui/search.cljs
@@ -51,6 +51,10 @@
 (defn status-icon [icon]
   (dom/img #js {:src (str "images/icon-" icon ".svg") :className "status"}))

+(defn basename [path]
+  (-> (.require js/window "path")
+      (.basename path)))
+
 (defn search-item [search]
   (let [{:keys [status path id]} search
         status-tr (get status-map status)
@@ -59,7 +63,7 @@
     (dom/div #js {:className (str "search flex-row " (name status))}
              (status-icon icon)
              (dom/div #js {:className "info flex"}
-                      (dom/div #js {:className "path"} path)
+                      (dom/div #js {:className "path"} (basename path))
                       (apply dom/div #js {:className "detail"} detail))
              (dom/div #js {:className "actions"}
                       (dom/div #js {:className "close" :onClick #(app/call :remove-search {:id id})} (dom/img #js {:src "images/icon-close.svg"}))


remove erroneous cljs.spec.alpha moved symbols

--- src/cljs_api_gen/moved.clj
+++ src/cljs_api_gen/moved.clj
@@ -46,7 +46,6 @@
    "cljs.spec.gen.alpha/large-integer*"
    "cljs.spec/exercise" "cljs.spec.alpha/exercise"
    "cljs.spec/cat" "cljs.spec.alpha/cat"
-   "cljs.spec/unstrument" "cljs.spec.alpha/unstrument"
    "cljs.spec.impl.gen/elements" "cljs.spec.gen.alpha/elements"
    "cljs.spec.test/abbrev-result" "cljs.spec.test.alpha/abbrev-result"
    "cljs.spec.impl.gen/symbol" "cljs.spec.gen.alpha/symbol"
@@ -68,7 +67,6 @@
    "cljs.spec/with-gen" "cljs.spec.alpha/with-gen"
    "cljs.spec/explain-str" "cljs.spec.alpha/explain-str"
    "cljs.spec/coll-of" "cljs.spec.alpha/coll-of"
-   "cljs.spec/instrument-ns" "cljs.spec.alpha/instrument-ns"
    "cljs.spec/unform" "cljs.spec.alpha/unform"
    "cljs.spec/def" "cljs.spec.alpha/def"
    "cljs.spec/nilable" "cljs.spec.alpha/nilable"
@@ -92,7 +90,6 @@
    "cljs.spec/get-spec" "cljs.spec.alpha/get-spec"
    "cljs.spec.impl.gen/fmap" "cljs.spec.gen.alpha/fmap"
    "cljs.spec.impl.gen/any" "cljs.spec.gen.alpha/any"
-   "cljs.spec.test/run-all-tests" "cljs.spec.test.alpha/run-all-tests"
    "cljs.spec.impl.gen/string-ascii" "cljs.spec.gen.alpha/string-ascii"
    "cljs.spec/&" "cljs.spec.alpha/&"
    "cljs.spec.test/checkable-syms" "cljs.spec.test.alpha/checkable-syms"
@@ -118,51 +115,36 @@
    "cljs.spec/explain" "cljs.spec.alpha/explain"
    "cljs.spec.impl.gen/char-ascii" "cljs.spec.gen.alpha/char-ascii"
    "cljs.spec.impl.gen/cat" "cljs.spec.gen.alpha/cat"
-   "cljs.spec/speced-vars*" "cljs.spec.alpha/speced-vars*"
    "cljs.spec/double-in" "cljs.spec.alpha/double-in"
    "cljs.spec.impl.gen/quick-check" "cljs.spec.gen.alpha/quick-check"
    "cljs.spec/?" "cljs.spec.alpha/?"
    "cljs.spec/*coll-error-limit*" "cljs.spec.alpha/*coll-error-limit*"
-   "cljs.spec/instrument-all" "cljs.spec.alpha/instrument-all"
-   "cljs.spec/instrument" "cljs.spec.alpha/instrument"
    "cljs.spec.impl.gen/set" "cljs.spec.gen.alpha/set"
    "cljs.spec.impl.gen/return" "cljs.spec.gen.alpha/return"
    "cljs.spec.test/get-ua-product" "cljs.spec.test.alpha/get-ua-product"
-   "cljs.spec/instrument*" "cljs.spec.alpha/instrument*"
    "cljs.spec.test/unstrument" "cljs.spec.test.alpha/unstrument"
    "cljs.spec.impl.gen/vector-distinct"
    "cljs.spec.gen.alpha/vector-distinct"
    "cljs.spec.test/get-env" "cljs.spec.test.alpha/get-env"
    "cljs.spec.impl.gen/double" "cljs.spec.gen.alpha/double"
-   "cljs.spec/unstrument-ns" "cljs.spec.alpha/unstrument-ns"
    "cljs.spec/fspec" "cljs.spec.alpha/fspec"
-   "cljs.spec/coll-gen" "cljs.spec.alpha/coll-gen"
    "cljs.spec/and" "cljs.spec.alpha/and"
    "cljs.spec/merge" "cljs.spec.alpha/merge"
    "cljs.spec.test/check" "cljs.spec.test.alpha/check"
-   "cljs.spec.test/enumerate-namespace"
-   "cljs.spec.test.alpha/enumerate-namespace"
    "cljs.spec/MAX_INT" "cljs.spec.alpha/MAX_INT"
    "cljs.spec/spec?" "cljs.spec.alpha/spec?"
-   "cljs.spec.test/check-var" "cljs.spec.test.alpha/check-var"
    "cljs.spec/regex?" "cljs.spec.alpha/regex?"
    "cljs.spec.impl.gen/frequency" "cljs.spec.gen.alpha/frequency"
    "cljs.spec.impl.gen/char" "cljs.spec.gen.alpha/char"
    "cljs.spec.impl.gen/simple-type" "cljs.spec.gen.alpha/simple-type"
    "cljs.spec.impl.gen/map" "cljs.spec.gen.alpha/map"
-   "cljs.spec/coll-checker" "cljs.spec.alpha/coll-checker"
    "cljs.spec.impl.gen/for-all*" "cljs.spec.gen.alpha/for-all*"
-   "cljs.spec/with-instrument-disabled"
-   "cljs.spec.alpha/with-instrument-disabled"
    "cljs.spec/assert" "cljs.spec.alpha/assert"
    "cljs.spec/multi-spec" "cljs.spec.alpha/multi-spec"
    "cljs.spec.test/check-1" "cljs.spec.test.alpha/check-1"
    "cljs.spec.test/checkable-syms*"
    "cljs.spec.test.alpha/checkable-syms*"
    "cljs.spec.impl.gen/dynaload" "cljs.spec.gen.alpha/dynaload"
-   "cljs.spec/fn-specs" "cljs.spec.alpha/fn-specs"
-   "cljs.spec/unstrument*" "cljs.spec.alpha/unstrument*"
-   "cljs.spec/unstrument-all" "cljs.spec.alpha/unstrument-all"
    "cljs.spec.impl.gen/string-alphanumeric"
    "cljs.spec.gen.alpha/string-alphanumeric"
    "cljs.spec.test/unstrument-1" "cljs.spec.test.alpha/unstrument-1"
@@ -170,7 +152,6 @@
    "cljs.spec/inst-in-range?" "cljs.spec.alpha/inst-in-range?"
    "cljs.spec.impl.gen/string" "cljs.spec.gen.alpha/string"
    "cljs.spec.impl.gen/keyword-ns" "cljs.spec.gen.alpha/keyword-ns"
-   "cljs.spec.test/run-tests" "cljs.spec.test.alpha/run-tests"
    "cljs.spec.impl.gen/keyword" "cljs.spec.gen.alpha/keyword"
    "cljs.spec/keys*" "cljs.spec.alpha/keys*"
    "cljs.spec/keys" "cljs.spec.alpha/keys"


ignore custom list of internals (close #74)

--- src/cljs_api_gen/parse.clj
+++ src/cljs_api_gen/parse.clj
@@ -249,6 +249,40 @@
 (defmethod parse-form* nil           [form] nil)

 ;;--------------------------------------------------------------------------------
+;; Ignore internal defs
+;;--------------------------------------------------------------------------------
+
+(def unlabeled-internals
+  "Internal symbols that are not labeled as such.
+  Each symbol will be ignored in the given version range pairs [add remove add remove ...etc]"
+  {"cljs.core/INIT"     [2301]
+   "cljs.core/START"    [2301]
+   "cljs.core/fixture1" [927]
+   "cljs.core/fixture2" [927]})
+
+(defn unlabeled-internal?
+  [form]
+  (when-let [version-ranges (unlabeled-internals (str (:ns form) "/" (:name form)))]
+    (some
+      (fn [[start end :as vrange]]
+        (and
+          (or (nil? start) (>= *cljs-num* start))
+          (or (nil? end)   (<  *cljs-num* end))))
+      (partition 2 2 [nil] version-ranges))))
+
+(defn internal-def-only?
+  [form]
+  (let [[c0 c1] (split (:potential-comment form) #"\s+")
+        comment-flag? (and (#{";;" ";"} c0)
+                           c1
+                           (= "internal" (lower-case c1)))
+        [d0] (split (or (:docstring form) "") #"\s+")
+        docstring-flag? (and d0 (= "internal" (lower-case d0)))]
+    (or comment-flag?
+        docstring-flag?
+        (unlabeled-internal? form))))
+
+;;--------------------------------------------------------------------------------
 ;; Parse common meta for defs
 ;;--------------------------------------------------------------------------------

@@ -285,16 +319,6 @@

       (when manual-macro?
         {:type "macro"}))))
-
-(defn internal-def-only?
-  [form]
-  (let [[c0 c1] (split (:potential-comment form) #"\s+")
-        comment-flag? (and (#{";;" ";"} c0)
-                           c1
-                           (= "internal" (lower-case c1)))
-        [d0] (split (or (:docstring form) "") #"\s+")
-        docstring-flag? (and d0 (= "internal" (lower-case d0)))]
-    (or comment-flag? docstring-flag?)))

 (defn parse-form
   [form]


DataFrame API slightly changed from JavaSchemaRDD API

--- src/clojure/flambo/sql.clj
+++ src/clojure/flambo/sql.clj
@@ -20,16 +20,16 @@
 (defn json-file [sql-context path]
   (.jsonFile sql-context path))

-(defn register-rdd-as-table [sql-context rdd table-name]
-  (.registerRDDAsTable sql-context rdd table-name))
+(defn register-data-frame-as-table [sql-context df table-name]
+  (.registerDataFrameAsTable sql-context df table-name))

 (defn cache-table [sql-context table-name]
   (.cacheTable sql-context table-name))

-;; ## JavaSchemaRDD
+;; ## DataFrame
 ;;
-(defn register-as-table [rdd table-name]
-  (.registerAsTable rdd table-name))
+(defn register-temp-table [df table-name]
+  (.registerTempTable df table-name))

 (def print-schema (memfn printSchema))


add zero arity `newline` to match Clojure


Exclude -lookup (cljs)

Exclude -lookup (cljs)

--- modules/reitit-core/src/reitit/core.cljc
+++ modules/reitit-core/src/reitit/core.cljc
@@ -1,4 +1,5 @@
 (ns reitit.core
+  (:refer-clojure :exclude [-lookup])
   (:require [meta-merge.core :refer [meta-merge]]
             [clojure.string :as str]
             [reitit.segment :as segment]


edn-reponse

edn-reponse

--- src/core/clj/virt/core.clj
+++ src/core/clj/virt/core.clj
@@ -38,10 +38,13 @@
   (let [id (atom 0x00B)]
     (fn [] (swap! id #(inc %)))))

-(defn channels-handler [request]
+(defn edn-response [body]
   {:status 200
    :headers {"Content-Type" "application/edn"}
-   :body (pr-str @channels)})
+   :body (pr-str body)})
+
+(defn channels-handler [request]
+  (edn-response @channels))

 (defn new-channel [channel-name]
   (let [new-id (next-id)]
@@ -53,9 +56,7 @@
                               :app :chat}}))))
       (alter chat-threads
         #(conj % {new-id {}}))))
-  {:status 200
-   :headers {"Content-Type" "application/edn"}
-   :body (pr-str @channels)})
+  (edn-response @channels))

 (defn new-channel-handler [request]
   (let [body (read-string (slurp (:body request)))]
@@ -64,16 +65,12 @@
 (defn chat-threads-handler [request]
   (let [params (:route-params request)
         channel-id (read-string (:channel-id params))]
-    {:status 200
-     :headers {"Content-Type" "application/edn"}
-     :body (pr-str (get @chat-threads channel-id))}))
+    (edn-response (get @chat-threads channel-id))))

 (defn chat-messages-handler [request]
   (let [params (:route-params request)
         thread-id (read-string (:thread-id params))]
-    {:status 200
-     :headers {"Content-Type" "application/edn"}
-     :body (pr-str (get @chat-messages thread-id))}))
+    (edn-response (get @chat-messages thread-id))))

 (defn new-chat-thread [channel-id thread-name]
   (let [new-id (next-id)]
@@ -84,9 +81,7 @@
             #(conj % {new-id {:title thread-name}}))))
       (alter chat-messages
         #(conj % {new-id []}))))
-  {:status 200
-   :headers {"Content-Type" "application/edn"}
-   :body (pr-str (get @chat-threads channel-id))})
+  (edn-response (get @chat-threads channel-id)))

 (defn new-chat-thread-handler [request]
   (let [body (read-string (slurp (:body request)))]


Symbolicating is not expensive.

Symbolicating is not expensive.

--- src/datomish/transact.cljc
+++ src/datomish/transact.cljc
@@ -401,22 +401,22 @@
                      {:error :schema/idents
                       :op    ia }))))))))

-(defn- symbolicate-datom [db [e a v tx added]]
-  (datom
-    (db/ident db e)
-    (db/ident db a)
-    (db/ident db v)
-    tx
-    added))
-
 (defn collect-db-install-assertions
   "Transactions may add idents, install new partitions, and install new schema attributes.
   Collect [:db.part/db :db.install/attribute] assertions here."
   [db report]
   {:pre [(db/db? db) (report? report)]}

-  ;; TODO: be more efficient; symbolicating each datom is expensive!
-  (let [datoms (map (partial symbolicate-datom db) (:tx-data report))
+  ;; Symbolicating is not expensive.
+  (let [symbolicate-install-datom
+        (fn [[e a v tx added]]
+          (datom
+            (db/ident db e)
+            (db/ident db a)
+            (db/ident db v)
+            tx
+            added))
+        datoms (map symbolicate-install-datom (:tx-data report))
         schema-fragment (datomish.schema-changes/datoms->schema-fragment datoms)]
     (assoc-in report [:added-attributes] schema-fragment)))


current-context needs to default to nil

current-context needs to default to nil

--- bake/bake/core.clj
+++ bake/bake/core.clj
@@ -23,8 +23,7 @@
   (boolean (or (:v *opts*) (:verbose *opts*))))

 (defn current-context []
-  (if-let [context (or (get-in *opts* [:context 0])
-                       (:context *project*))]
+  (if-let [context (get-in *opts* [:context 0])]
     (symbol context)))

 (defn project-with-context [context]
@@ -33,7 +32,7 @@
               :context context)))

 (defmacro with-context [context & forms]
-  `(let [context# (symbol (name ~context))]
+  `(let [context# (symbol (name (or ~context (:context *project*))))]
      (binding [*project* (project-with-context context#)]
        ~@forms)))


Pre-format datetimes in last observation data fetch

Date formatting without proper datetime support is a pain in the
backside so pre-format datetimes already in backend.

--- src/env_logger/handler.clj
+++ src/env_logger/handler.clj
@@ -128,21 +128,36 @@
         token)
       response-unauthorized)))

+(defn convert-epoch-ms-to-tring
+  "Converts an Unix epoch timestamp to a 'human readable' value."
+  [epoch-ts]
+  (t/format "d.L.Y HH:mm:ss"
+            (t/plus (t/zoned-date-time
+                     (str (Instant/ofEpochMilli epoch-ts)))
+                    (t/hours (db/get-tz-offset
+                              (get-conf-value :store-timezone))))))
+
 (defn get-last-obs-data
   "Get data for observation with a non-null FMI temperature value."
   [request]
   (if-not (authenticated? request)
     response-unauthorized
-    {:status 200
-     :body {:data (first (filter #(not (nil? (:fmi_temperature %)))
-                                 (reverse (db/get-obs-days db/postgres 1))))
-            :rt-data (take (count (get-conf-value :ruuvitag-locations))
-                           (reverse (db/get-ruuvitag-obs
-                                     db/postgres
-                                     (t/minus (t/local-date-time)
-                                              (t/minutes 45))
-                                     (t/local-date-time)
-                                     (get-conf-value :ruuvitag-locations))))}}))
+    (let [data (first (filter #(not (nil? (:fmi_temperature %)))
+                              (reverse (db/get-obs-days db/postgres 1))))
+          rt-data (take (count (get-conf-value :ruuvitag-locations))
+                        (reverse (db/get-ruuvitag-obs
+                                  db/postgres
+                                  (t/minus (t/local-date-time)
+                                           (t/minutes 45))
+                                  (t/local-date-time)
+                                  (get-conf-value :ruuvitag-locations))))]
+      {:status 200
+       :body {:data (assoc data :recorded
+                           (convert-epoch-ms-to-tring (:recorded data)))
+              :rt-data (for [item rt-data]
+                         (assoc item :recorded
+                                (convert-epoch-ms-to-tring
+                                 (:recorded item))))}})))

 (defn yc-image-validity-check
   "Checks whether the yardcam image has the right format and is not too old.


Leftover.

Leftover.

--- src/examples/followbot.clj
+++ src/examples/followbot.clj
@@ -17,7 +17,7 @@
        (abs (- (:z from) (:z to))))))

 (defn- toward-single [from to]
-  (if (<= (abs (- from to)) 1)
+  (if (<= (abs (- from to)) 2)
     0
     (if (< from to) 1 -1)))

@@ -38,15 +38,13 @@
                      (distance-between bot %2))
                  entities))))

+
 ; Loops ----------------------------------------------------------------------------
 (defn follow [bot]
   (when (:loc @(:player bot))
     (let [players (find-other-players bot)
           closest (closest-entity bot players)]
       (when closest
-        (println (:name @(:player bot)) "following" (:name @closest))
-        (println (:loc @(:player bot)))
-        (println (:loc @closest))
         (let [{x :x z :z} (toward bot closest)]
           [(actions/move bot x 0 z)])))))