Added support to retrieve iso formats by concept-id.

--- src/cmr/search/services/acls/acl_helper.clj
+++ src/cmr/search/services/acls/acl_helper.clj
@@ -38,6 +38,15 @@
         sids (context->sids context)]
     (filter (partial acl-matches-sids-and-permission? sids :read) acls)))

+(defn- get-iso-access-value
+  "Returns the iso-mends access value by parsing MENDS ISO xml"
+  [concept]
+  (when-let [[_ restriction-flag-str]
+             (re-matches #"(?s).*<gco:CharacterString>Restriction Flag:(.+?)</gco:CharacterString>.*"
+                         (:metadata concept))]
+    (when-not (re-find #".*<.*" restriction-flag-str)
+      (Double. ^String restriction-flag-str))))
+
 (defmulti extract-access-value
   "Extracts access value (aka. restriction flag) from the concept."
   (fn [concept]
@@ -52,4 +61,17 @@
 (defmethod extract-access-value "application/dif+xml"
   [concept]
   ;; DIF doesn't support restriction flag yet.
-  nil)+  nil)
+
+(defmethod extract-access-value "application/iso+xml"
+  [concept]
+  (get-iso-access-value concept))
+
+(defmethod extract-access-value "application/iso-mends+xml"
+  [concept]
+  (get-iso-access-value concept))
+
+(defmethod extract-access-value "application/iso-smap+xml"
+  [concept]
+  ;; SMAP ISO doesn't support restriction flag yet.
+  nil)


(PDB-1031) Speed migration with unique facts table

Copy just (factset_id, path, hash) to a temporary table and then use
that to rebuild facts once we've eliminated the duplicates from
fact_paths and fact_values.  In tests, this improved performance
substantially.

cf. (PDB-1224)

[rlb@puppetlabs.com: adjust commit message; adjust for migration
 updates]

--- src/com/puppetlabs/puppetdb/scf/migrate.clj
+++ src/com/puppetlabs/puppetdb/scf/migrate.clj
@@ -891,62 +891,26 @@
   (sql/do-commands
    ;; Build complete facts table as of migration 28.

-   "CREATE TABLE facts_transform
+   "CREATE TABLE facts_unique_transform
       (factset_id bigint NOT NULL,
-       fact_path_id bigint NOT NULL,
-       fact_value_id bigint NOT NULL)"
-
-   ;; We need these indexes for the insertion and upcoming deletions.
+       fact_path text NOT NULL,
+       fact_value_hash varchar(40) NOT NULL)"
+
+   "INSERT INTO facts_unique_transform (factset_id, fact_path, fact_value_hash)
+      SELECT f.factset_id, fp.path, fv.value_hash
+        FROM facts f
+        INNER JOIN fact_values fv on f.fact_value_id = fv.id
+        INNER JOIN fact_paths fp on fv.path_id = fp.id"
+
+   "DROP TABLE facts"
+
+   ;; We need these indexes for the upcoming deletions.
    ;; A deletion like this doesn't need the index, but it only works
    ;; with PostgreSQL:
    ;;   DELETE FROM fact_values t1 USING fact_values t2
    ;;     WHERE t1.value_hash = t2.value_hash AND t1.id > t2.id
    "CREATE INDEX fact_path_path_idx ON fact_paths(path)"
    "CREATE INDEX fact_values_value_hash_idx ON fact_values(value_hash)"
-
-   ;; Patch up facts refrences to refer to the min id path/value
-   ;; wherever there's more than one option.
-   "INSERT INTO facts_transform (factset_id, fact_path_id, fact_value_id)
-      SELECT f.factset_id,
-             (SELECT MIN(id) FROM fact_paths fp2 WHERE fp2.path = fp.path),
-             (SELECT MIN(id) FROM fact_values fv2
-                WHERE fv2.value_hash = fv.value_hash)
-          FROM facts f
-            INNER JOIN fact_values fv on f.fact_value_id = fv.id
-            INNER JOIN fact_paths fp on fv.path_id = fp.id"
-   "DROP TABLE facts"
-
-   "ALTER TABLE facts_transform
-      ADD CONSTRAINT facts_factset_id_fact_path_id_fact_key
-        UNIQUE (factset_id, fact_path_id)"
-   "ALTER TABLE facts_transform
-      ADD CONSTRAINT factset_id_fk
-        FOREIGN KEY (factset_id) REFERENCES factsets(id)
-        ON UPDATE CASCADE
-        ON DELETE CASCADE"
-
-   "ALTER TABLE facts_transform
-         ADD CONSTRAINT fact_path_id_fk
-           FOREIGN KEY (fact_path_id) REFERENCES fact_paths(id)"
-   "ALTER TABLE facts_transform
-         ADD CONSTRAINT fact_value_id_fk
-           FOREIGN KEY (fact_value_id) REFERENCES fact_values(id)"
-
-   "ALTER TABLE facts_transform RENAME TO facts"
-   "CREATE INDEX facts_fact_path_id_idx ON facts(fact_path_id)"
-   "CREATE INDEX facts_fact_value_id_idx ON facts(fact_value_id)"
-
-   (if (scf-utils/postgres?) "ANALYZE facts" "SELECT 1")
-
-   ;; These are for the more pedantic HSQLDB.
-   "ALTER TABLE fact_paths DROP CONSTRAINT fact_paths_path_type_id_key"
-   "ALTER TABLE fact_paths DROP CONSTRAINT fact_paths_value_type_id"
-   "DROP INDEX fact_paths_value_type_id"
-   "ALTER TABLE fact_values DROP CONSTRAINT fact_values_path_id_value_key"
-   "ALTER TABLE fact_values DROP CONSTRAINT fact_values_path_id_fk"
-
-   "ALTER TABLE fact_paths DROP COLUMN value_type_id"
-   "ALTER TABLE fact_values DROP COLUMN path_id"

    ;; Remove all the orphaned duplicates (all but the row in each set
    ;; with min-id).
@@ -963,7 +927,55 @@
    "ALTER TABLE fact_paths
       ADD CONSTRAINT fact_paths_path_key UNIQUE (path)"
    "ALTER TABLE fact_values
-      ADD CONSTRAINT fact_values_value_hash_key UNIQUE (value_hash)"))
+      ADD CONSTRAINT fact_values_value_hash_key UNIQUE (value_hash)"
+
+   "CREATE TABLE facts_transform
+      (factset_id bigint NOT NULL,
+       fact_path_id bigint NOT NULL,
+       fact_value_id bigint NOT NULL)"
+
+   ;; Patch up facts refrences to refer to the min id path/value
+   ;; wherever there's more than one option.
+   "INSERT INTO facts_transform (factset_id, fact_path_id, fact_value_id)
+      SELECT f.factset_id, fp.id, fv.id
+        FROM facts_unique_transform f
+        INNER JOIN fact_paths fp on f.fact_path = fp.path
+        INNER JOIN fact_values fv on f.fact_value_hash = fv.value_hash;"
+
+   "DROP TABLE facts_unique_transform"
+
+   "ALTER TABLE facts_transform
+      ADD CONSTRAINT facts_factset_id_fact_path_id_fact_key
+        UNIQUE (factset_id, fact_path_id)"
+
+   "ALTER TABLE facts_transform
+      ADD CONSTRAINT factset_id_fk
+        FOREIGN KEY (factset_id) REFERENCES factsets(id)
+        ON UPDATE CASCADE
+        ON DELETE CASCADE"
+
+   "ALTER TABLE facts_transform
+         ADD CONSTRAINT fact_path_id_fk
+           FOREIGN KEY (fact_path_id) REFERENCES fact_paths(id)"
+   "ALTER TABLE facts_transform
+         ADD CONSTRAINT fact_value_id_fk
+           FOREIGN KEY (fact_value_id) REFERENCES fact_values(id)"
+
+   "ALTER TABLE facts_transform RENAME TO facts"
+   "CREATE INDEX facts_fact_path_id_idx ON facts(fact_path_id)"
+   "CREATE INDEX facts_fact_value_id_idx ON facts(fact_value_id)"
+
+   (if (scf-utils/postgres?) "ANALYZE facts" "SELECT 1")
+
+   ;; These are for the more pedantic HSQLDB.
+   "ALTER TABLE fact_paths DROP CONSTRAINT fact_paths_path_type_id_key"
+   "ALTER TABLE fact_paths DROP CONSTRAINT fact_paths_value_type_id"
+   "DROP INDEX fact_paths_value_type_id"
+   "ALTER TABLE fact_values DROP CONSTRAINT fact_values_path_id_value_key"
+   "ALTER TABLE fact_values DROP CONSTRAINT fact_values_path_id_fk"
+
+   "ALTER TABLE fact_paths DROP COLUMN value_type_id"
+   "ALTER TABLE fact_values DROP COLUMN path_id"))

 ;; The available migrations, as a map from migration version to migration function.
 (def migrations


Guard when selected-entity-type is empty, which happens when there's no data (#579)

--- src/cljs/org/broadinstitute/firecloud_ui/common/entity_table.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/common/entity_table.cljs
@@ -82,9 +82,10 @@
             [Table
              (merge props
                     {:key selected-entity-type
-                     :state-key (str (common/workspace-id->string (:workspace-id props)) ":data" selected-entity-type)
+                     :state-key (when selected-entity-type
+                                  (str (common/workspace-id->string (:workspace-id props)) ":data" selected-entity-type))
                      :columns columns
-                     :column-defaults (get (:column-defaults props) (name selected-entity-type))
+                     :column-defaults (get (:column-defaults props) (some-> selected-entity-type name))
                      :always-sort? true
                      :pagination (react/call :pagination this)
                      :filter-groups (map (fn [type]


a comma

a comma

--- damp.ekeko.aspectj.plugin/src/damp/ekeko/aspectj/soot.clj
+++ damp.ekeko.aspectj.plugin/src/damp/ekeko/aspectj/soot.clj
@@ -144,7 +144,7 @@

 (defn
   advice-soot|calling|unit-soot|calling|method
-  "Relation between an advice and the Soot unit and method that calls it."
+  "Relation between an advice, and the Soot unit and method that calls it."
   [?advice ?soot|calling|unit ?soot|calling|method]
   (fresh [?soot|method]
          (advice-soot|method ?advice ?soot|method)


Remove comment

Remove comment

--- src/expound/alpha.cljc
+++ src/expound/alpha.cljc
@@ -279,21 +279,6 @@
         {:expound/keys [form in]} problem
         type (:expound.spec.problem/type problem)]
     (value-str type spec-name form in problems opts)))
-
-;; a path may be converted into something we can use and find the inner value
-;; or it may not, and so value-in WON'T be able to handle it, because
-;; value-in expects a certain type of path
-;; third-party libs like spell-spec expect to be able to call value-in
-;; directly with an expound-path, so ideally value-in would be able to handle
-;; this broader type of path, but what's a sensible return value when you give
-;; it a path that doesn't map to a value? some error value that itself must
-;; be handled?
-
-;; perhaps a back-compat way to deal with it is to make value-in return
-;; a ::not-found value but in my implementation of the handler just use
-;; val/path directly to figure out a strategy to print in value-in-context
-;; .... hmmm
-;;

 ;; FIXME - when I decide to break compatibility for value-str-fn, maybe
 ;; make it show conform/unformed value


Adds assertions

Adds assertions

--- src/expound/alpha.cljc
+++ src/expound/alpha.cljc
@@ -322,7 +322,7 @@
            nil))))

 ;; TODO - maybe just return these values in an easy to destructure map
-;; TODo - move to new namespace
+;; TODO - move to new namespace
 (defn ^:private problem-parts [problem opts]
   (let [type (:expound.spec.problem/type problem)
         spec-name nil ;; TODO - fix
@@ -347,17 +347,12 @@
 (def ^:private format-str "%s\n\n%s\n\n%s")

 (defn ^:private format-err [header type spec-name form in problems opts expected]
-  ;; TODO remove
-  (s/assert qualified-keyword? type)
   (printer/format
    format-str
    (header-label header)
-   ;; TODO - use new multimethod?
    (value-str type spec-name form in problems opts)
-   #_(show-spec-name spec-name (printer/indent (*value-str-fn* spec-name form in (problems/value-in form in))))
    expected))

-;; HERE ---
 (defmethod expected-str :problem/value-group [_type spec-name val path problems opts]
   (let [problem (first problems)
         subproblems (:problems problem)
@@ -366,8 +361,9 @@
      "\n\nor\n\n"
      (map #(expected-str2 % opts) grouped-subproblems))))

+;; TODO - namespace to expound
 (defmethod value-str :problem/value-group [type spec-name val path problems opts]
-  ;; TODO - assert singleton
+  (s/assert ::singleton problems)
   (let [problem (first problems)
         subproblems (:problems problem)
         {:keys [form in type]} (problem-parts (first subproblems) opts)]
@@ -421,7 +417,7 @@
           (expected-str2 [problem] opts)))))))

 (defmethod problem-group-str :problem/alt-group [_type spec-name val path problems opts]
-  ;; TODO - assert singleton problems
+  (s/assert ::singleton problems)
   (printer/format
    "%s\n\n%s"
    (header-label "Spec failed")


removed mins and secs

removed mins and secs


put awt-events in the right place

put awt-events in the right place

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@7108 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- plugins/DataBrowser/src/org/micromanager/browser/core.clj
+++ plugins/DataBrowser/src/org/micromanager/browser/core.clj
@@ -24,7 +24,8 @@
            [java.util.prefs Preferences]
            [java.util.concurrent LinkedBlockingQueue]
            [java.awt Color Dimension Font Insets]
-           [java.awt.event ItemEvent ItemListener KeyAdapter MouseAdapter]
+           [java.awt.event ItemEvent ItemListener KeyAdapter MouseAdapter
+                           WindowAdapter WindowListener]
            [com.swtdesigner SwingResourceManager]
            [org.micromanager.acquisition ImageStorageListener MMImageCache])
   (:use [org.micromanager.browser.utils
@@ -38,6 +39,8 @@

 (def browser (atom nil))

+(def browser-status (atom "Idle"))
+
 (def settings-window (atom nil))

 (def collections (atom nil))
@@ -65,9 +68,15 @@
   "UUID" "UserName" "Width" "z-step_um"
    ])

+(defn clear-queues []
+  (.clear pending-locations)
+  (.clear pending-data-sets)
+  (while (not= @browser-status "Idle") (Thread/sleep 10)))
+
 (defn set-browser-status [text]
   (-> @browser :frame
-      (.setTitle (str "Micro-Manager Data Set Browser (" text ")"))))
+      (.setTitle (str "Micro-Manager Data Set Browser (" text ")")))
+  (reset! browser-status text))

 (defn get-icon [name]
   (SwingResourceManager/getIcon
@@ -219,6 +228,7 @@
             (fn []
               (dorun (loop []
                 (try
+                  (Thread/sleep 5)
                   (let [location (.take pending-locations)]
                     (if-not (= location pending-locations)
                       (do (doseq [data-set (find-data-sets location)]
@@ -226,14 +236,15 @@
                             (.put pending-data-sets [data-set location]))
                           (recur))
                     nil))
-                  (catch Exception e nil)))))) .start))
+                  (catch Exception e nil)))))
+          "data browser scanning thread") .start))

 (defn start-reading-thread []
   (doto (Thread.
             (fn []
               (dorun (loop []
-                (set-browser-status
-                  (if (empty? pending-data-sets) "Idle" "Scanning"))
+                (Thread/sleep 5)
+                (when (empty? pending-data-sets) (set-browser-status "Idle"))
                 (try
                   (let [data-set (.take pending-data-sets)]
                     (if-not (= data-set pending-data-sets)
@@ -241,11 +252,13 @@
                         (add-browser-table-row (map #(get m %) tags))
                         (recur))
                       nil))
-                  (catch Exception e nil)))))) .start))
+                  (catch Exception e nil)))))
+          "data browser reading thread") .start))

 (defn add-location [location]
   (swap! current-locations conj location)
   (.put pending-locations location)
+  (set-browser-status "Scanning")
   (awt-event (-> @settings-window :locations :table .getModel .fireTableDataChanged)))

 (defn user-add-location []
@@ -389,6 +402,7 @@

 (defn apply-data-and-settings [collection-name settings]
+  (clear-queues)
   (update-collection-menu collection-name)
   (set-last-collection-name collection-name)
   (let [table (@browser :table)
@@ -397,10 +411,11 @@
                 browser-model-headings
                 window-size display-columns
                 locations sorted-column]} settings]
-    (awt-event
+  ;  (awt-event
       (def dc display-columns)
       (reset! current-data (map (fn [r] (map #(get r (keyword %)) tags)) browser-model-data))
-      (.fireTableDataChanged model)
+      (.fireTableDataChanged model);)
+  ;  (awt-event
       (reset! current-locations (apply sorted-set locations))
       (-> @settings-window :locations :table .getModel .fireTableDataChanged)
       (remove-all-columns table)
@@ -409,7 +424,7 @@
           (doto (add-browser-column (:title col))
             (.setPreferredWidth (* total-width (:width col))))))
       (-> @settings-window :columns :table
-                           .getModel .fireTableDataChanged))))
+                           .getModel .fireTableDataChanged)));)

 ;; creating a new collection

@@ -435,7 +450,8 @@
         (swap! collections assoc collection-name
           (.getAbsolutePath (File. (str collection-name ".mmdb.txt"))))
         (save-collection-map)
-        (apply-data-and-settings collection-name (fresh-data-and-settings)))
+        (awt-event
+          (apply-data-and-settings collection-name (fresh-data-and-settings))))
       (update-collection-menu (get-last-collection-name)))))

 (defn create-image-storage-listener []
@@ -445,8 +461,7 @@
       (.put pending-data-sets [path ""]))))

 (defn refresh-collection []
-  (.clear pending-locations)
-  (.clear pending-data-sets)
+  (clear-queues)
   (dorun (map add-location @current-locations)))

 ;; windows
@@ -502,7 +517,7 @@
         (if (= (.getStateChange e) ItemEvent/SELECTED)
           (condp = item
             "New..." (create-new-collection)
-            (apply-data-and-settings item (load-data-and-settings item)))
+            (awt-event (apply-data-and-settings item (load-data-and-settings item))))
           (save-data-and-settings item (get-current-data-and-settings)))))))

 (defn create-browser []
@@ -542,7 +557,15 @@
     (listen-to-open table)
     (attach-action-key search-field "ESCAPE" #(.setText search-field ""))
     (doto frame
-      (.setBounds 50 50 620 500))
+      (.setBounds 50 50 620 500)
+      (.addWindowListener
+        (proxy [WindowAdapter] []
+          (windowClosing [e]
+            (println frame)
+            (save-data-and-settings
+              (get-last-collection-name)
+                (get-current-data-and-settings))
+            (.setVisible frame false)))))
     (gen-map frame table scroll-pane settings-button search-field
              collection-menu refresh-button)))

@@ -558,10 +581,9 @@
   (start-scanning-thread)
   (start-reading-thread)
   (MMImageCache/addImageStorageListener (create-image-storage-listener))
-  (.setModel (:table @browser) (create-browser-table-model tags))
-  (let [collection-name (get-last-collection-name)]
-    (apply-data-and-settings collection-name (load-data-and-settings collection-name)))
-  (awt-event (.show (@browser :frame)))
+  (awt-event
+    (.show (@browser :frame))
+    (.setModel (:table @browser) (create-browser-table-model tags))
+    (let [collection-name (get-last-collection-name)]
+      (apply-data-and-settings collection-name (load-data-and-settings collection-name))))
   browser)
-
-


STORM-3137: Fix too strict mock verification in nimbus_test

--- storm-core/test/clj/org/apache/storm/nimbus_test.clj
+++ storm-core/test/clj/org/apache/storm/nimbus_test.clj
@@ -1829,11 +1829,6 @@
         (.setLogConfig nimbus "foo" mock-config)
         (.setTopologyLogConfig (Mockito/verify cluster-state) (Mockito/any String) (Mockito/eq expected-config) (Mockito/any Map))))))

-(defn teardown-heartbeats [id])
-(defn teardown-topo-errors [id])
-(defn teardown-backpressure-dirs [id])
-(defn teardown-wt-dirs [id])
-
 (defn mock-cluster-state
   ([]
     (mock-cluster-state nil nil))
@@ -1842,16 +1837,13 @@
   ([active-topos hb-topos error-topos bp-topos]
     (mock-cluster-state active-topos hb-topos error-topos bp-topos nil))
   ([active-topos hb-topos error-topos bp-topos wt-topos]
-    (reify IStormClusterState
-      (teardownHeartbeats [this id] (teardown-heartbeats id))
-      (teardownTopologyErrors [this id] (teardown-topo-errors id))
-      (removeBackpressure [this id] (teardown-backpressure-dirs id))
-      (removeAllPrivateWorkerKeys [this id] (teardown-wt-dirs id))
-      (activeStorms [this] active-topos)
-      (heartbeatStorms [this] hb-topos)
-      (errorTopologies [this] error-topos)
-      (backpressureTopologies [this] bp-topos)
-      (idsOfTopologiesWithPrivateWorkerKeys [this] (into #{} wt-topos)))))
+    (let [cluster-state (Mockito/mock IStormClusterState)]
+      (.thenReturn (Mockito/when (.activeStorms cluster-state)) active-topos)
+      (.thenReturn (Mockito/when (.heartbeatStorms cluster-state)) hb-topos)
+      (.thenReturn (Mockito/when (.errorTopologies cluster-state)) error-topos)
+      (.thenReturn (Mockito/when (.backpressureTopologies cluster-state)) bp-topos)
+      (.thenReturn (Mockito/when (.idsOfTopologiesWithPrivateWorkerKeys cluster-state)) (into #{} wt-topos))
+      cluster-state)))

 (deftest cleanup-storm-ids-returns-inactive-topos
          (let [mock-state (mock-cluster-state (list "topo1") (list "topo1" "topo2" "topo3"))
@@ -1892,19 +1884,16 @@
       (let [nimbus (Mockito/spy (Nimbus. conf nil mock-state nil mock-blob-store nil nil))]
         (.set (.getHeartbeatsCache nimbus) hb-cache)
         (.thenReturn (Mockito/when (.storedTopoIds mock-blob-store)) (HashSet. inactive-topos))
-        (mocking
-          [teardown-heartbeats
-           teardown-topo-errors]

           (.doCleanup nimbus)

           ;; removed heartbeats znode
-          (verify-nth-call-args-for 1 teardown-heartbeats "topo2")
-          (verify-nth-call-args-for 2 teardown-heartbeats "topo3")
+          (.teardownHeartbeats (Mockito/verify mock-state) "topo2")
+          (.teardownHeartbeats (Mockito/verify mock-state) "topo3")

           ;; removed topo errors znode
-          (verify-nth-call-args-for 1 teardown-topo-errors "topo2")
-          (verify-nth-call-args-for 2 teardown-topo-errors "topo3")
+          (.teardownTopologyErrors (Mockito/verify mock-state) "topo2")
+          (.teardownTopologyErrors (Mockito/verify mock-state) "topo3")

           ;; removed topo directories
           (.forceDeleteTopoDistDir (Mockito/verify nimbus) "topo2")
@@ -1919,7 +1908,7 @@
           (.rmDependencyJarsInTopology (Mockito/verify nimbus) "topo3")

           ;; remove topos from heartbeat cache
-          (is (= (count (.get (.getHeartbeatsCache nimbus))) 0)))))))
+          (is (= (count (.get (.getHeartbeatsCache nimbus))) 0))))))

 (deftest do-cleanup-does-not-teardown-active-topos
@@ -1933,21 +1922,18 @@
       (let [nimbus (Mockito/spy (Nimbus. conf nil mock-state nil mock-blob-store nil nil))]
         (.set (.getHeartbeatsCache nimbus) hb-cache)
         (.thenReturn (Mockito/when (.storedTopoIds mock-blob-store)) (set inactive-topos))
-        (mocking
-          [teardown-heartbeats
-           teardown-topo-errors]

           (.doCleanup nimbus)

-          (verify-call-times-for teardown-heartbeats 0)
-          (verify-call-times-for teardown-topo-errors 0)
+          (.teardownHeartbeats (Mockito/verify mock-state (Mockito/never)) (Mockito/any))
+          (.teardownTopologyErrors (Mockito/verify mock-state (Mockito/never)) (Mockito/any))
           (.forceDeleteTopoDistDir (Mockito/verify nimbus (Mockito/times 0)) (Mockito/anyObject))
           (.rmTopologyKeys (Mockito/verify nimbus (Mockito/times 0)) (Mockito/anyObject))

           ;; hb-cache goes down to 1 because only one topo was inactive
           (is (= (count (.get (.getHeartbeatsCache nimbus))) 2))
           (is (contains? (.get (.getHeartbeatsCache nimbus)) "topo1"))
-          (is (contains? (.get (.getHeartbeatsCache nimbus)) "topo2")))))))
+          (is (contains? (.get (.getHeartbeatsCache nimbus)) "topo2"))))))

 (deftest user-topologies-for-supervisor
   (let [assignment (doto (Assignment.)


Small change to browser repl demo

Small change to browser repl demo

--- repl-demo/browser/cljs/replumb_repl/console/cljs.cljs
+++ repl-demo/browser/cljs/replumb_repl/console/cljs.cljs
@@ -12,35 +12,34 @@
     (write-fn console (replumb/unwrap-result result))))

 (defn cljs-read-eval-print!
-  [console line]
+  [console repl-opts line]
   (try
-    (replumb/read-eval-call (merge (replumb/browser-options ["/src/cljs" "/js/compiled/out"]
-                                                            io/fetch-file!)
-                                   {:warning-as-error true})
-                            (partial handle-result! console)
-                            line)
+    (replumb/read-eval-call repl-opts (partial handle-result! console) line)
     (catch js/Error err
       (println "Caught js/Error during read-eval-print: " err)
       (console/write-exception! console err))))

 (defn cljs-console-prompt!
-  [console]
+  [console repl-opts]
   (doto console
     (.Prompt true (fn [input]
-                    (cljs-read-eval-print! console input)
+                    (cljs-read-eval-print! console repl-opts input)
                     (.SetPromptLabel console (replumb/get-prompt)) ;; necessary for namespace changes
-                    (cljs-console-prompt! console)))))
+                    (cljs-console-prompt! console repl-opts)))))

 (defn cljs-console-did-mount
   [console-opts]
   (js/$
    (fn []
-     (let [jqconsole (console/new-jqconsole "#cljs-console"
+     (let [repl-opts (merge (replumb/browser-options ["/src/cljs" "/js/compiled/out"]
+                                                     io/fetch-file!)
+                            {:warning-as-error true})
+           jqconsole (console/new-jqconsole "#cljs-console"
                                             (merge {:prompt-label (replumb/get-prompt)
                                                     :disable-auto-focus true}
                                                    console-opts))]
        (app/add-console! :cljs-console jqconsole)
-       (cljs-console-prompt! jqconsole)))))
+       (cljs-console-prompt! jqconsole repl-opts)))))

 (defn cljs-console-render []
   [:div.console-container


Init! right when the app starts

Init! right when the app starts

--- src/time_tracker/core.clj
+++ src/time_tracker/core.clj
@@ -17,7 +17,6 @@
 (defn start-server!
   ([] (start-server! (web-service/app)))
   ([app-handler]
-   (init!)
    (log/info {:event ::server-start})
    (let [stop-fn (httpkit/run-server app-handler
                                      {:port (Integer/parseInt (util/from-config :port))})]
@@ -28,6 +27,7 @@

 (defn -main
   [& args]
+  (init!)
   (condp = (first args)
     "migrate"  (migrate-db)
     "rollback" (rollback-db)


Refactored responses.clj

Refactored responses.clj

--- src/skat/responses.clj
+++ src/skat/responses.clj
@@ -8,13 +8,10 @@
   (let [filtered (filter fun coll)]
     (if (empty? filtered) coll filtered)))
 (defn allow-trumph-then-color-then-everything [trumph? c coll]
-  (let [trumphs (filter trumph? coll)]
-    (if (trumph? c)
-      trumphs
-      (letfn [(not-trumph? [c2]
-                (and (not (trumph? c2))
-                     (cards/property-matches? :color (:color c) c2)))]
-        (filter-if-not-empty not-trumph? coll)))))
+  (letfn [(not-trumph? [c2]
+            (and (not (trumph? c2))
+                 (cards/property-matches? :color (:color c) c2)))]
+    (filter-if-not-empty (if (trumph? c) trumph? not-trumph?) coll)))

 (defn W? [c]
   (cards/property-matches? :figure :W c))


bugfix: start-server takes attr-cluster and graph-cluster

--- src/blackbox/src/leela/blackbox/network/zmqserver.clj
+++ src/blackbox/src/leela/blackbox/network/zmqserver.clj
@@ -256,5 +256,5 @@
 (defn zmqworker [attr-cluster graph-cluster]
   {:onjob #(handle-message attr-cluster graph-cluster %) :onerr (msg-fail 500)})

-(defn server-start [ctx cluster options]
-  (router/router-start ctx (zmqworker cluster) options))
+(defn server-start [ctx attr-cluster graph-cluster options]
+  (router/router-start ctx (zmqworker attr-cluster graph-cluster) options))


(PE-32764) Update default ciphers

(PE-32764) Update default ciphers

This makes several changes to the default cipher lists for Jetty.
- Removes the TLS_CHACHA20_POLY1305_SHA256 cipher, as it is currently unsupported in Java 11.
- Adds TLS_DHE_RSA ciphers as recommended by the Mozilla Intermediate list.
- Adds the RSA version of the ECDHE AES 256 cipher to the FIPS list. Since our CA issues RSA-type certs/keys, we effectively only had one useable cipher.
- Rearranges the cipher list to be in the preferred order.

--- src/puppetlabs/trapperkeeper/services/webserver/jetty9_config.clj
+++ src/puppetlabs/trapperkeeper/services/webserver/jetty9_config.clj
@@ -60,24 +60,24 @@
 ;;; keep these overrides.
 (def tls-1-dot-3-ciphers
   ["TLS_AES_128_GCM_SHA256"
-   "TLS_AES_256_GCM_SHA384"
-   "TLS_CHACHA20_POLY1305_SHA256"])
+   "TLS_AES_256_GCM_SHA384"])

 (def tls-1-dot-2-ciphers
-  ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
+  ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
+   "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
-   "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
-   "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
-   "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
-   "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"])
+   "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
+   "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
+   "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"])

 (def acceptable-ciphers
   (into [] (concat tls-1-dot-3-ciphers tls-1-dot-2-ciphers)))

 (def fips-tls-1-dot-2-ciphers
-  ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
+  ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
+   "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
-   "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"])
+   "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"])

 (def acceptable-ciphers-fips
   (into [] (concat tls-1-dot-3-ciphers fips-tls-1-dot-2-ciphers)))


fix typo in ff osc metadata

fix typo in ff osc metadata

--- src/overtone/sc/machinery/ugen/metadata/ff_osc.clj
+++ src/overtone/sc/machinery/ugen/metadata/ff_osc.clj
@@ -14,7 +14,7 @@

        :doc "Very fast sine wave generator (2 PowerPC instructions per
              output sample!) implemented using a ringing filter.  This
-             generates a much cleane sine wave than a table lookup
+             generates a much cleaner sine wave than a table lookup
              oscillator and is a lot faster. However, the amplitude of
              the wave will vary with frequency. Generally the amplitude
              will go down as you raise the frequency and go up as you


Rename `-test` functions to `-check`, if they're checks


:sparkles: Handle mouse movement outside viewport

--- frontend/src/uxbox/main/ui/workspace/viewport.cljs
+++ frontend/src/uxbox/main/ui/workspace/viewport.cljs
@@ -189,6 +189,22 @@
              (when (= 2 (.-which event))
                (st/emit! ::finish-positioning)))))

+        on-pointer-down
+        (mf/use-callback
+          (fn [event]
+           (let [target (dom/get-target event)]
+             ; Capture mouse pointer to detect the movements even if cursor
+             ; leaves the viewport or the browser itself
+             ; https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture
+             (.setPointerCapture target (.-pointerId event)))))
+
+        on-pointer-up
+        (mf/use-callback
+          (fn [event]
+           (let [target (dom/get-target event)]
+             ; Release pointer on mouse up
+             (.releasePointerCapture target (.-pointerId event)))))
+
         on-click
         (mf/use-callback
          (fn [event]
@@ -352,6 +368,8 @@
       :on-double-click on-double-click
       :on-mouse-down on-mouse-down
       :on-mouse-up on-mouse-up
+      :on-pointer-down on-pointer-down
+      :on-pointer-up on-pointer-up
       :on-drag-over on-drag-over
       :on-drop on-drop}
      [:g


Added download links

Added download links

--- src/video_server/html.clj
+++ src/video_server/html.clj
@@ -40,8 +40,9 @@
                      (:video container)
                      (:audio container)
                      (format-size (:size container))
-                     (format-filetype (:filetype container))]
-                    (remove str/blank?)
+                     [:a {:href (:url container) :download nil}
+                      (format-filetype (:filetype container))]]
+                    (remove #(if (string? %) (str/blank? %)))
                     (map #(vector :td %)))])))

 (defn video-link


CMR-2011: Addressed a review comment.

CMR-2011: Addressed a review comment.

--- system-int-test/test/cmr/system_int_test/virtual_product_test.clj
+++ system-int-test/test/cmr/system_int_test/virtual_product_test.clj
@@ -225,7 +225,7 @@
                         :provider-id "LPDAAC_ECS")])
         vp-colls (vp/ingest-virtual-collections [ast-coll])
         ast-gran (vp/ingest-source-granule "LPDAAC_ECS"
-                           (dg/granule ast-coll {:granule-ur "SC:AST_L1A.003:2006227720"}))
+                                           (dg/granule ast-coll {:granule-ur "SC:AST_L1A.003:2006227720"}))
         prov-ast-coll (d/ingest "PROV"
                                 (dc/collection
                                   {:entry-title ast-entry-title}))
@@ -340,11 +340,11 @@
     (testing "If virtual products is disabled, there should be no translation"
       (try (dev-sys-util/eval-in-dev-sys
              `(cmr.virtual-product.config/set-virtual-products-enabled! false))
-        (let [request-json [source-granule non-virtual-granule1 virtual-granule1 non-virtual-granule2
-                            non-virtual-granule3 non-virtual-granule4 virtual-granule2 virtual-granule3]
+        (let [granule-entries [source-granule non-virtual-granule1 virtual-granule1 non-virtual-granule2
+                               non-virtual-granule3 non-virtual-granule4 virtual-granule2 virtual-granule3]
               response (vp/translate-granule-entries
-                         (json/generate-string request-json))]
-          (= request-json (json/parse-string (:body response) true)))
+                         (json/generate-string granule-entries))]
+          (= granule-entries (json/parse-string (:body response) true)))
         (finally (dev-sys-util/eval-in-dev-sys
                    `(cmr.virtual-product.config/set-virtual-products-enabled! true)))))))


CMR-1772: Added a doc string for a function.

--- system-int-test/test/cmr/system_int_test/virtual_product_test.clj
+++ system-int-test/test/cmr/system_int_test/virtual_product_test.clj
@@ -186,6 +186,7 @@
                                       :page-size 50}))))))

 (defn- assert-virtual-gran-revision-id
+  "Assert that the revision ids of the granules of the collections vp-colls match expected-revision-id"
   [vp-colls expected-revision-id]
   (doseq [revision-id  (mapcat #(map :revision-id (:refs (search/find-refs
                                                             :granule {:entry-title (:entry-title %)


Guard against error on browsers that don't have Notifications object

--- src/braid/core/client/ui/views/pages/global_settings.cljs
+++ src/braid/core/client/ui/views/pages/global_settings.cljs
@@ -119,7 +119,8 @@

 (defn notification-settings-view
   []
-  (let [notifications-enabled (r/atom (notify/enabled?))]
+  (let [notifications-enabled (r/atom (and (notify/has-notify?)
+                                           (notify/enabled?)))]
     (fn []
       [:div.setting
        [:h2 "Notification Preferences"]
@@ -133,10 +134,10 @@
              [:button
               {:on-click
                (fn [_] (notify/request-permission
-                        (fn [perm]
-                          (when (= perm "granted")
-                            (reset! notifications-enabled true)
-                            (notify/notify {:msg "Notifications Enabled!"})))))}
+                         (fn [perm]
+                           (when (= perm "granted")
+                             (reset! notifications-enabled true)
+                             (notify/notify {:msg "Notifications Enabled!"})))))}
               "Enable Desktop Notifications"])
            [notification-rules-view]]
           [:p "The browser you're currently using doesn't support notifications. "


Unzip changelogs in regression test to fix build

--- src/test/clojure/pdok/featured/regression_test.clj
+++ src/test/clojure/pdok/featured/regression_test.clj
@@ -2,8 +2,6 @@
   (:require [pdok.featured
              [dynamic-config :as dc]
              [config :as config]
-             [persistence :as persistence]
-             [geoserver :as geoserver]
              [timeline :as timeline]
              [processor :as processor]
              [extracts :as e]
@@ -11,15 +9,15 @@
             [pdok.postgres :as pg]
             [pdok.transit :as t]
             [clojure.math.combinatorics :as combo]
-            [clojure.core.async :as a
-             :refer [>! <! >!! <!! go chan]]
+            [clojure.core.async :refer [>! <! >!! <!! go chan]]
             [clojure.java.jdbc :as j]
             [clojure.test :refer :all]
             [clojure.java.io :as io]
             [clojure.string :as str]
             [pdok.filestore :as fs])
-  (:import (java.util UUID)
-           (java.io File)))
+  (:import (java.io File)
+           (java.util UUID)
+           (java.util.zip ZipInputStream)))

 (def test-db config/processor-db)
 (def changelog-dir (io/file (str (System/getProperty "java.io.tmpdir") "/featured-regression")))
@@ -59,7 +57,7 @@
         [meta features] (json-reader/features-from-stream stream)]
     [meta features]))

-(defn- inserted-features [extracts dataset extract-type collection features]
+(defn- inserted-features [extracts _ _ _ features]
   (let [new-extracts (map #(vector (:_version %) (:_valid_from %) (:_valid_to %) %) features)]
     (swap! extracts concat new-extracts)))

@@ -73,9 +71,9 @@
                           (= valid-from (nth %1 1))) extracts)
       (remove #(= version (nth % 0)) extracts))))

-(defn- deleted-versions [extracts dataset collection extract-type records]
-    (doseq [record records]
-      (swap! extracts remove-extract-record record)))
+(defn- deleted-versions [extracts _ _ _ records]
+  (doseq [record records]
+    (swap! extracts remove-extract-record record)))

 (defn- query [table selector]
   (when (pg/table-exists? test-db "featured_regression_regression-set" table)
@@ -242,8 +240,10 @@
   (let [[expected-dataset expected-collection expected-records]
         (with-open [in (io/reader expected-changelog)] (parse-changelog in))
         filestore (config/filestore changelog-dir)
-        parsed-changelogs (doall (map (fn [log] (with-open [in (io/input-stream (fs/get-file filestore log))]
-                                                  (parse-changelog in))) changelogs))
+        parsed-changelogs (doall (map (fn [log] (with-open [in (io/input-stream (fs/get-file filestore log))
+                                                            zip (ZipInputStream. in)]
+                                                  (.getNextEntry zip)
+                                                  (parse-changelog zip))) changelogs))
         all-records (mapcat (fn [[_ _ records]] records) parsed-changelogs)]
     (is (every? #(= [expected-dataset expected-collection] %) (->> parsed-changelogs (map (partial take 2)))))
     (is (every? #(not (nil? %)) (->> all-records (filter #(#{:new :change :close} (:action %))) (map :feature))))


Revamp command-line parsing; now use real subtasks

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -95,7 +95,7 @@
         nnproj (with-meta nproj nmeta)]
     nnproj))

-(defn ver-parse
+(defn ^:info-subtask ver-parse
   "Parses jar-path-like-string or artifact-version-string to find ctime and sha.
    Can handle cases in the range of:
      1.2.3-20120219223112-abc123f
@@ -228,9 +228,10 @@

 (defn install-versioned-artifact
   [proot]
-  (let [install-cmd ["lein" "voom" "install" :dir proot]
+  ;; TODO: voom build-deps first, then wrap install:
+  (let [install-cmd ["lein" "voom" "wrap" "install" :dir proot]
         _ (apply println "install-versioned-artifact:" install-cmd)
-        rtn (sh "lein" "voom" "install" :dir proot)]
+        rtn (apply sh install-cmd)]
     (when-not (zero? (:exit rtn))
       (throw (ex-info "lein voom install error" (assoc rtn :cmd install-cmd))))
     rtn))
@@ -616,7 +617,25 @@
           input-str
           replacement-map))

-(defn freshen [project & args]
+(defn freshen
+  "Modify dependency versions in this project.clj based on what's available in $VOOM_REPOS
+
+  Fetches latest upstream commits for all repos in $VOOM_REPOS (usually
+  ~/.voom-repos), index-tags those commits as needed, and then finds
+  the latest version for each dependency that matches any voom
+  metadata applied to the dep. Updates the project.clj file in place
+  with the version found.
+
+  Metadata on a dep can restrict versions found based on :repo,
+  :branch, path, and partial :version.  For example:
+  ^{:voom {:version \"1\", :path \"modules/foo\"}} [bar/foo \"1.0.0\"]
+
+  Will only update deps that can be found as lein projects in
+  $VOOM_REPOS, so you may need to manually clone new working copies
+  there so voom can find your deps.
+
+  Example: lein voom freshen"
+  [project]
   (p-repos (fn [p] (fetch-all [p]) (tag-repo-projects p)))
   (let [prj-file-name (str (:root project) "/project.clj")
         old-deps (:dependencies project)
@@ -681,7 +700,7 @@
             f)]
     (apply adj-path d elems)))

-(defn ^File find-box
+(defn ^:info-subtask ^File find-box
   "Locates voom-box root starting from current working directory."
   []
   (loop [^File path (or *pwd* (-> "user.dir" System/getProperty File.))]
@@ -747,7 +766,7 @@
 (defn box-add
   [proj & adeps]
   (p-repos (fn [p] (tag-repo-projects p)))
-  (doseq [:let [deps (fold-args-as-meta adeps)]
+  (doseq [:let [deps (fold-args-as-meta (map edn/read-string adeps))]
           dep deps
           :let [full-projs (if (.contains (str dep) "/")
                              [dep]
@@ -807,42 +826,72 @@

 ;; === lein entrypoint ===

-;; TODO: Consider revamping these entry points. Separate top-level
-;; lein commands?  Separate lein plugins?
-(defn ^:no-project-needed voom
-  "Usage:
-    lein voom [flags] [lein command ...]
-      Runs lein command with a project version augmented with git
-      version of the most recent change of this project directory.
-      Flags include:
-        :insanely-allow-dirty-working-copy - by default voom
-          refuses to handle a dirty working copy
-        :no-upstream - by default voom wants to see the current
-          version reachable via an upstream repo
-        :long-sha - uses a full length sha instead of the default
-          short form
-    lein voom [:long-sha] :print
-    lein voom :parse <version-str>"
+(defn wrap
+  "Execute any lein task, but using git info as this project's version qualifier.
+
+   Usage: lein voom wrap [<flags>] <lein task name> <lein task args>
+
+   Flags:
+     :insanely-allow-dirty-working-copy - by default voom sanely
+         refuses to generate a voom-version from a dirty working copy
+     :long-sha - uses a full length sha instead of the default
+         short form
+
+   Example: lein voom wrap install"
   [project & args]
   (let [[kw-like more-args] (split-with #(re-find #"^:" %) args)
         kargset (set (map edn/read-string kw-like))
-        sargs (map edn/read-string more-args)
-        long-sha (kargset :long-sha)
-        new-project (delay (update-proj-version project long-sha))]
+        new-project (update-proj-version project (:long-sha kargset))]
     ;; TODO throw exception if upstream doesn't contain this commit :no-upstream
-    (cond
-     (:print kargset) (println (:version @new-project))
-     (:parse kargset) (prn (ver-parse (first more-args)))
-     (:find-box kargset) (prn (find-box))
-     (:box kargset) (apply box project more-args)
-     (:box-new kargset) (apply box-new project more-args)
-     (:box-init kargset) (apply box-init project more-args)
-     (:box-add kargset) (apply box-add project (map edn/read-string more-args))
-     (:box-remove kargset) (apply box-remove project more-args)
-     (:retag-all-repos kargset) (time (p-repos (fn [p] (clear-voom-tags p) (tag-repo-projects p))))
-     (:freshen kargset) (freshen project)
-     (:build-deps kargset) (build-deps project)
-     :else (if (and (dirty-wc? (:root @new-project))
-                    (not (:insanely-allow-dirty-working-copy kargset)))
-             (lmain/abort "Refusing to continue with dirty working copy. (Hint: Run 'git status')")
-             (lmain/resolve-and-apply @new-project more-args)))))
+    ;;    :no-upstream - by default voom wants to see the current
+    ;;      version reachable via an upstream repo
+    (if (and (dirty-wc? (:root new-project))
+             (not (:insanely-allow-dirty-working-copy kargset)))
+      (lmain/abort "Refusing to continue with dirty working copy. (Hint: Run 'git status')")
+      (lmain/resolve-and-apply new-project more-args))))
+
+(defn install
+  "Same as 'lein voom wrap install': install a voom-versioned artifact of this project.
+
+  Example: lein voom install"
+  [project & args]
+  (apply wrap project "install" args))
+
+(defn deploy
+  "Same as 'lein voom wrap deploy': deploy a voom-versioned artifact of this project.
+
+  Example: lein voom deploy clojars"
+  [project & args]
+  (apply wrap project "deploy" args))
+
+(defn retag-all-repos
+  "Clear and recreate all voom index tags in $VOOM_REPOS.
+
+  You shouldn't need to use this usually because the index tags are
+  automatically added incrementally and re-generated when tag schemas
+  change.
+
+  Example: lein voom retag-all-repos"
+  [_]
+  (time (p-repos (fn [p] (clear-voom-tags p) (tag-repo-projects p)))))
+
+(def subtasks [#'build-deps #'deploy #'find-box #'freshen #'install
+               #'retag-all-repos #'ver-parse #'wrap])
+
+(def internal-subtasks [#'box #'box-new #'box-init #'box-add #'box-remove])
+
+(defn ^:no-project-needed ^{:subtasks subtasks} voom
+  "Generate and use artifacts versioned with git commit and commit time.
+
+  There are several subtasks, as well as the 'box' script which has
+  several commands of its own, built using this plugin."
+  [project subtask-name & args]
+
+  (let [subtask-var (resolve (symbol "leiningen.voom"
+                                     (s/replace subtask-name #"^:" "")))]
+    (if-let [subtask (some #{subtask-var} (concat subtasks internal-subtasks))]
+      (if (:info-subtask (meta subtask))
+        (prn (apply subtask args))
+        (apply subtask project args))
+      (println "No voom subtask found" (prn-str subtask-name)
+               " Try: lein help voom"))))


Fix cases where git history simplification was causing pain.

Specifically, merge commits were being omitted if a path
simplification was in effect.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -534,7 +534,7 @@
               , (map
                  parse-sha-refs
                  (:lines (apply git {:gitdir gitdir} "log"
-                                "--pretty=format:%H,%cd,%p,%d" "--reverse"
+                                "--pretty=format:%H,%cd,%p,%d" "--full-history" "--reverse"
                                 (concat neg-tags [(str "origin/" found-branch) "--" found-path]))))]
         :when (seq commits)]
     (let [refs (-> commits first :refs)


Fix spec for older version

Fix spec for older version

--- test/expound/alpha_test.cljc
+++ test/expound/alpha_test.cljc
@@ -3628,7 +3628,8 @@
           (if (spec-error-in-ex-msg?)
             (is (thrown-with-msg?
                  #?(:cljs :default :clj Exception)
-                 #"should have additional elements. The next element \"\:init\-expr\" should satisfy"
+                 ;;#"(?i)should satisfy\s+even-number-of-forms\?"
+                 #"even-number-of-forms\?"
                  (macroexpand '(clojure.core/let [a] 2))))
             (let [ed (try
                        (macroexpand '(clojure.core/let [a] 2))


print form being evalled in bake when there is an exception

--- bake/bake.clj
+++ bake/bake.clj
@@ -16,12 +16,18 @@
 (defmacro deftask "Just ignore deftask calls in bake."
   [name & body])

+(defn eval-verbose [form]
+  (try (eval form)
+       (catch Exception e
+         (println "evaluating form:" (prn-str form))
+         (throw e))))
+
 (defn eval-multi [form]
   (clojure.main/with-bindings
     (binding [project @bake-project]
       (if (vector? form)
-        (doseq [f form] (eval f))
-        (eval form)))))
+        (doseq [f form] (eval-verbose f))
+        (eval-verbose form)))))

 (defn quit []
   (if (= 0 (swank/num-connections))


[skip ci] Update docstrings

[skip ci] Update docstrings

--- build.boot
+++ build.boot
@@ -45,6 +45,7 @@
 ;; Util

 (def windows?
+  "True if running on windows."
   (.. (System/getProperty "os.name") (toLowerCase) (startsWith "windows")))

 (defn fix-slashes
@@ -55,7 +56,7 @@
     s))

 (defn proc
-  "Returns a task which runs the args as a shell command."
+  "Runs the args as a shell command."
   [& args]
   (with-pass-thru _
     (-> (ProcessBuilder. args)
@@ -66,6 +67,7 @@
 ;; Config

 (def cljs-compiler-opts
+  "Default ClojureScript compiler options."
   {:static-fns         true
    :fn-invoke-direct   true
    :parallel-build     true
@@ -76,10 +78,12 @@
    :closure-defines    {'macrowbar.util/DEBUG true}})

 (def cljs-test-namespaces
+  "Default ClojureScript test namespaces."
   '[mikron.runtime.core-test
     mikron.runtime.buffer-test])

 (def clj-test-namespaces
+  "Default Clojure test namespaces."
   (conj cljs-test-namespaces 'mikron.runtime.core-test2))

 ;; Tasks
@@ -197,8 +201,7 @@
         (speak)))

 (deftask run-node-repl
-  "Runs a node repl.
-   TODO does not work - waiting on Lumo closure libs support."
+  "Runs a node repl."
   []
   (comp (testing)
         (benchmarking)


Update paren-soup

Update paren-soup

--- build.boot
+++ build.boot
@@ -43,7 +43,7 @@
   (set-env! :dependencies
     (conj (get-env :dependencies)
       '[org.clojure/clojurescript "1.9.225"]
-      '[paren-soup "2.6.4"]
+      '[paren-soup "2.6.5"]
       '[cljsjs/codemirror "5.19.0-0"]))
   (comp (cljs :optimizations :advanced) (target)))


Fix font-awesome version issue + remove boot-s3

--- build.boot
+++ build.boot
@@ -22,7 +22,6 @@
    [datascript "0.15.4"]
    [deraen/boot-sass "0.3.0" :scope "test"]
    [devcards "0.2.2" :scope "test"]
-   [hashobject/boot-s3 "0.1.2-SNAPSHOT" :scope "test"]
    [hiccup "1.0.5"]
    [org.clojure/clojure "1.9.0-alpha14"]
    [org.clojure/clojurescript "1.9.293"]
@@ -50,7 +49,6 @@
  '[crisptrutski.boot-cljs-test :refer [test-cljs]]
  '[danielsz.autoprefixer :refer [autoprefixer]]
  '[deraen.boot-sass :refer :all]
- '[hashobject.boot-s3 :refer :all]
  '[io.perun :refer :all]
  '[org.martinklepsch.boot-gzip :refer [gzip]]
  '[pandeiro.boot-http :refer :all])
@@ -64,11 +62,11 @@
   []
   (comp
    (sift :add-jar {'org.webjars/bootstrap-sass #"META-INF/resources/webjars/bootstrap-sass/3\.3\.7/stylesheets/.*\.scss$"
-                   'org.webjars/font-awesome #"META-INF/resources/webjars/font-awesome/4\.6\.3/(fonts|scss/.*\.scss)"})
+                   'org.webjars/font-awesome #"META-INF/resources/webjars/font-awesome/4\.7\.0/(fonts|scss/.*\.scss)"})
    (sift :move {#"META-INF/resources/webjars/bootstrap-sass/3\.3\.7/stylesheets" "bootstrap"
-                #"META-INF/resources/webjars/font-awesome/4\.6\.3/fonts" "fonts"
-                #"META-INF/resources/webjars/font-awesome/4\.6\.3/scss/(_.*\.scss)" "font-awesome/$1"
-                #"META-INF/resources/webjars/font-awesome/4\.6\.3/scss/font-awesome.scss" "font-awesome/_font-awesome.scss"})
+                #"META-INF/resources/webjars/font-awesome/4\.7\.0/fonts" "fonts"
+                #"META-INF/resources/webjars/font-awesome/4\.7\.0/scss/(_.*\.scss)" "font-awesome/$1"
+                #"META-INF/resources/webjars/font-awesome/4\.7\.0/scss/font-awesome.scss" "font-awesome/_font-awesome.scss"})
    (sift :to-source #{#"bootstrap" #"font-awesome"}
          :to-resource #{#"fonts"})
    (sass :options {:precision 8})


bump version

bump version

--- build.boot
+++ build.boot
@@ -6,7 +6,7 @@

 (require '[tailrecursion.boot-useful :refer :all])

-(def +version+ "0.0-2371-3")
+(def +version+ "0.0-2371-4")

 (useful! +version+)


Dependencies: Bump a few dependencies to make boot dev work again

--- build.boot
+++ build.boot
@@ -29,10 +29,12 @@
                  [inflections "0.13.0"]
                  [org.clojure/clojure "1.9.0-alpha15"]
                  [org.clojure/clojurescript "1.9.495"]
+                 [org.clojure/core.async "0.3.442"]
                  [org.omcljs/om "1.0.0-alpha48"]
                  [org.clojure/data.json "0.2.6"]

                  ;; Development dependencies
+                 [org.clojure/tools.nrepl "0.2.12" :scope "test"]
                  [devcards "0.2.1-6" :scope "test"]
                  [datascript "0.15.5" :scope "test"]])


version bump up

version bump up

--- build.boot
+++ build.boot
@@ -26,7 +26,7 @@
                  [ring-middleware-format "0.7.2"]
                  [digest "1.4.8"]])

-(def +version+ "1.0.0")
+(def +version+ "1.0.1")

 ;; to check the newest versions:
 ;; boot -d boot-deps ancient


Fix join tests

Fix join tests

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -448,6 +448,8 @@
   (key [this]
        (when (false? end?)
          (aget array ix)))
+  (val [this]
+       nil)
   (next [this]
         (set! ix (+ ix 1))
         (if (>= ix (alength array))
@@ -837,7 +839,8 @@
         join-results (apply-to-iterator
                       (join #js [(iterator tree) (iterator tree)] key-len #js [(into-array (repeat key-len true)) (into-array (repeat key-len true))])
                       movements)]
-    (= (map vec iterator-results) (map vec join-results))))
+    (= (map (fn [[b k]] [b (vec k)]) iterator-results)
+       (map (fn [[b k]] [b (vec k)]) join-results))))

 (defn self-join-prop [key-len]
   (prop/for-all [min-keys gen/s-pos-int
@@ -851,13 +854,14 @@
         elems (iterator->keys (iterator tree))
         _ (dotimes [i (alength elems)]
             (dotimes [j (alength elems)]
-              (.assoc! product-tree (.concat (aget elems i 0) (aget elems j 0)) nil)))
+              (.assoc! product-tree (.concat (aget elems i) (aget elems j)) nil)))
         iterator-results (apply-to-iterator (iterator product-tree) movements)
         join-results (apply-to-iterator
                       (join #js [(iterator tree) (iterator tree)] (* 2 key-len) #js [(into-array (concat (repeat key-len true) (repeat key-len false)))
                                                                                (into-array (concat (repeat key-len false) (repeat key-len true)))])
                       movements)]
-    (= (map vec iterator-results) (map vec join-results))))
+    (= (map (fn [[b k]] [b (vec k)]) iterator-results)
+       (map (fn [[b k]] [b (vec k)]) join-results))))

 (defn product-join-prop [key-len]
   (prop/for-all [min-keys gen/s-pos-int


Fix iterators

Fix iterators

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -110,43 +110,48 @@
               (assert (every? #(< (aget keys %) (.-lower (aget children (inc %)))) (range (count keys))))
               (dotimes [i (count children)] (.valid! (aget children i)))))))

-(deftype Iterator [max-keys ^:mutable node ^:mutable ix]
-  ;; always points to before a valid key or to the tree wrapper
+(deftype Iterator [max-keys ^:mutable node ^:mutable ix ^:mutable end?]
   Object
   (next [this]
-        (when (instance? Node node)
+        (when-not end?
           (if (nil? (.-children node))
             (do
               (set! ix (+ ix 1))
               (loop []
-                (when (and (instance? Node node) (>= ix (alength (.-keys node))))
+                (if (>= ix (alength (.-keys node)))
+                  (if (instance? Node (.-parent node))
+                    (do
+                      (set! ix (.-parent-ix node))
+                      (set! node (.-parent node))
+                      (recur))
+                    (do
+                      (set! end? true)
+                      nil))
+                  #js [(aget (.-keys node) ix) (aget (.-vals node) ix)])))
+            (do
+              (set! node (aget (.-children node) (+ ix 1)))
+              (set! ix 0)
+              #js [(aget (.-keys node) ix) (aget (.-vals node) ix)]))))
+  (seek [this key]
+        (when-not end?
+          (loop []
+            (if (> key (.-upper node))
+              (if (instance? Node (.-parent node))
+                (do
                   (set! ix (.-parent-ix node))
                   (set! node (.-parent node))
-                  (recur))))
-            (do
-              (set! node (aget (.-children node) (+ ix 1)))
-              (set! ix 0)))
-          (when (instance? Node node)
-            #js [(aget (.-keys node) ix) (aget (.-vals node) ix)])))
-  (seek [this key] ;; move the iterator forwards until it reaches a key greater than this one
-        ;; head across and upwards until we reach a greater key
-        (loop []
-          (when (instance? Node node)
-            (set! ix (.seek node key ix))
-            (when (and (>= ix (alength (.-keys node))) (instance? Node (.-parent node)))
-              (set! ix (.-parent-ix node))
-              (set! node (.-parent node))
-              (recur))))
-        ;; head downwards and across until we reach the least greater key
-        (loop []
-          (when (instance? Node node)
-            (when-not (or (nil? (.-children node)) (== key (aget (.-keys node) ix)))
-              (set! node (aget (.-children node) ix))
-              (set! ix (.seek node key 0))
-              (recur))))
-        ;; if we aren't now at the tree wrapper we can return a result
-        (when (and (instance? Node node) (< ix (alength (.-keys node))))
-          #js [(aget (.-keys node) ix) (aget (.-vals node) ix)])))
+                  (recur))
+                (do
+                  (set! end? true)
+                  nil))
+              (do
+                (set! ix (.seek node key ix))
+                (if (and (not (nil? (.-children node))) (< key (aget (.-keys node) ix)))
+                  (do
+                    (set! node (aget (.-children node) ix))
+                    (set! ix 0)
+                    (recur))
+                  #js [(aget (.-keys node) ix) (aget (.-vals node) ix)])))))))

 (defn iterator [tree]
   (loop [node (.-root tree)]
@@ -162,6 +167,9 @@
     tree))

 (comment
+  (let [node (Node. nil nil #js [])]
+    (.seek node 0 0))
+
   (let [node (Node. nil nil #js [0])]
     (.seek node 0 0))

@@ -242,6 +250,10 @@

   (let [tree (tree 3)
         iterator (iterator tree)]
+    (.next iterator))
+
+  (let [tree (tree 3)
+        iterator (iterator tree)]
     (take 2000 (take-while identity (repeatedly #(.next iterator)))))

   (let [tree (tree 3)
@@ -253,7 +265,11 @@
         _ (dotimes [i 1000]
             (.assoc! tree i (* 2 i)))
         iterator (iterator tree)]
-    (take 2000 (take-while identity (repeatedly #(.next iterator)))))
+    (= (for [i (range 1000)] [i (* 2 i)]) (map #(.apply vector nil %) (take 2000 (take-while identity (repeatedly #(.next iterator)))))))
+
+  (let [tree (tree 3)
+        iterator (iterator tree)]
+    (.seek iterator -100))

   (let [tree (tree 3)
         _ (dotimes [i 1000]


more logging

more logging

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -175,7 +175,7 @@
         from-bolt bolt ;; so we can show what (add-complement) did to the input bolt, for logging.
         bolt-spec (get-in bolt path :no-path)
         spec (unifyc spec bolt-spec)]
-    (log/debug (str "add-complement at path: " path " to bolt with bolt:["
+    (log/trace (str "add-complement at path: " path " to bolt with bolt:["
                     (if (map? bolt) (get-in bolt [:rule]))
                     " '" (morph bolt) "'"
                     "]"))
@@ -184,7 +184,7 @@
     (if (not (= bolt-spec :no-path)) ;; check if this bolt has this path in it.
       (let [immediate-parent (get-in bolt (butlast path))
             start-time (current-time)
-            cached (if cache
+            cached (if (and true cache)
                      (do
                        (let [result (get-lex immediate-parent :comp cache spec)]
                          (if (not (nil? result))
@@ -193,7 +193,7 @@
                                                            #"\.(..).*"
                                                            (fn [[_ two-digits]] (str "." two-digits))))))
                          result))
-                     (do (log/warn (str "no cache: will go through entire lexicon."))
+                     (do (log/trace (str "no cache: will go through entire lexicon."))
                          nil))
             complement-candidate-lexemes (if cached cached (flatten (vals lexicon)))]
         (let [semantics (get-in spec [:synsem :sem])]
@@ -226,20 +226,22 @@
               (filter (fn [result]
                         (not (fail? result)))
                       (map (fn [complement]
-                             (let [debug (log/debug (str "add complement ["
-                                                         (get-in bolt [:rule]) " "
-                                                         (morph bolt) "]: trying lexical complement:" (morph complement)
-                                                         ))
+                             (let [debug
+                                   (if (or true (= (morph bolt) "alzarsi"))
+                                     (log/debug (str "add complement ["
+                                                     (get-in bolt [:rule]) " "
+                                                     (morph bolt) "]: trying lexical complement:" (morph complement)
+                                                     )))
                                    result
-                                   (unify  (copy bolt)
-                                           (path-to-map path
+                                   (unify (copy bolt)
+                                          (path-to-map path
                                                         (copy complement)))
                                    is-fail? (fail? result)]
                                (if is-fail?
                                  (do
-                                   (log/trace (str "fail-path-between:" (fail-path-between (strip-refs (get-in bolt path))
-                                                                                (strip-refs complement)))))
-                                 (log/trace (str "Success: returning: " (morph complement))))
+                                   (log/debug (str "fail-path-between(bolt=val1/comp=val2):" (fail-path-between (strip-refs (get-in bolt path))
+                                                                                (strip-refs complement)))))
+                                 (log/debug (str "Success: returning: " (morph result))))

                                (if is-fail? :fail result)))

@@ -253,9 +255,12 @@

               ;; else, no complements could be added to this bolt: Throw an exception
               (let [message
-                    (str " add-complement to " (get-in bolt [:rule]) " took " run-time " msec, but found no lexical complements for "
+                    (str " add-complement to " (get-in bolt [:rule]) " at path: " path " took " run-time " msec, but found no lexical complements for "
                          "'" (morph from-bolt) "'"
-                         ". Desired complement cat was: " (strip-refs (get-in bolt (concat path [:synsem :cat])))
+;                         ". Desired complement cat was: " (strip-refs (get-in bolt (concat path [:synsem :cat])))
+                         ". Desired complement synsem/sem/pred was: " (strip-refs (get-in bolt (concat path [:synsem :sem :pred])))
+;                         ". Head is:" (strip-refs (get-in bolt (concat (butlast path) [:head])))
+                         ". Head notes:" (strip-refs (get-in bolt (concat (butlast path) [:head :notes])))
                          ". Complements tried were:"
                          (str " " (string/join "," (map morph (take 5 complement-candidate-lexemes))) ".. and "
                               (- (count complement-candidate-lexemes) 5) " more."))]


add repl timeout

add repl timeout

just so it unlocks the read after a while when not getting
a result back.

--- src/main/shadow/cljs/devtools/server/repl_impl.clj
+++ src/main/shadow/cljs/devtools/server/repl_impl.clj
@@ -255,8 +255,19 @@
                      (recur repl-state))

                    (do (tap> [:unexpected-from-relay msg repl-state worker relay])
-                       (recur repl-state)))
-                 ))))]
+                       (recur repl-state)))))
+
+              (async/timeout 10000)
+              ([_]
+               ;; fine to wait long time while reading
+               (if (= :read (:stage repl-state))
+                 (recur repl-state)
+                 ;; should time out eventually while waiting for eval/print so you can retry
+                 (do (>!! read-lock 1)
+                     (repl-stderr repl-state (str "Timeout while waiting for result.\n"))
+                     (-> repl-state
+                         (assoc :stage :read)
+                         (recur)))))))]

       (async/close! to-relay)
       (async/close! read-lock)


deflakes test-request-queue-timeout-max-instances-limit (#323)

--- waiter/integration/waiter/request_timeout_test.clj
+++ waiter/integration/waiter/request_timeout_test.clj
@@ -14,8 +14,7 @@
 ;; limitations under the License.
 ;;
 (ns waiter.request-timeout-test
-  (:require [clj-time.core :as time]
-            [clojure.core.async :as async]
+  (:require [clj-time.core :as t]
             [clojure.string :as str]
             [clojure.test :refer :all]
             [clojure.tools.logging :as log]
@@ -25,7 +24,7 @@

 (defmacro assert-failed-request [service-name response-body start-time-ms timeout-period-sec faulty-app?]
   `(let [end-time-ms# (System/currentTimeMillis)
-         elapsed-time-secs# (time/in-seconds (time/millis (- end-time-ms# ~start-time-ms)))]
+         elapsed-time-secs# (t/in-seconds (t/millis (- end-time-ms# ~start-time-ms)))]
      (is (>= elapsed-time-secs# ~timeout-period-sec))
      (is (str/includes? ~response-body (str "After " ~timeout-period-sec " seconds, no instance available to handle request.")))
      (when ~faulty-app?
@@ -106,7 +105,7 @@
 (deftest ^:parallel ^:integration-fast test-request-queue-timeout-slow-start-app
   (testing-using-waiter-url
     (let [timeout-period-sec 10
-          timeout-period-ms (time/in-millis (time/seconds timeout-period-sec))
+          timeout-period-ms (t/in-millis (t/seconds timeout-period-sec))
           start-time-ms (System/currentTimeMillis)
           start-up-sleep-ms (* 2 timeout-period-ms)
           request-headers (walk/stringify-keys
@@ -130,85 +129,62 @@
                              :x-waiter-cmd-type "shell"
                              :x-waiter-cmd "sleep 5"
                              :x-waiter-health-check-url "/status"
-                             :x-waiter-queue-timeout (time/in-millis (time/seconds timeout-period-sec))})]
+                             :x-waiter-queue-timeout (t/in-millis (t/seconds timeout-period-sec))})]
       (make-request-and-assert-timeout waiter-url request-headers start-time-ms timeout-period-sec false)
       (delete-service waiter-url request-headers))))

-; Marked explicit due to:
-; FAIL in (test-request-queue-timeout-unable-to-scale-app)
-;  Body:Hello World
-; expected: (clojure.core/= 503 actual-status__18382__auto__)
-;   actual: (not (clojure.core/= 503 200))
-;
-; FAIL in (test-request-queue-timeout-unable-to-scale-app)
-; expected: (>= elapsed-time-secs timeout-period-sec)
-;   actual: (not (>= 0 15))
-;
-; FAIL in (test-request-queue-timeout-unable-to-scale-app)
-; expected: (str/includes? response-body "requests-waiting-to-stream: 0")
-;   actual: (not (str/includes? "Hello World" "requests-waiting-to-stream: 0"))
-;
-; FAIL in (test-request-queue-timeout-unable-to-scale-app)
-; expected: (str/includes? response-body "waiting-for-available-instance: 1")
-;   actual: (not (str/includes? "Hello World" "waiting-for-available-instance: 1"))
-(deftest ^:parallel ^:integration-slow ^:explicit test-request-queue-timeout-unable-to-scale-app
-  (testing-using-waiter-url
-    (let [timeout-period-sec 15
-          long-request-period-ms 30000
-          service-name (rand-name)
-          request-headers (walk/stringify-keys
-                            (merge (kitchen-request-headers)
-                                   {:x-waiter-name service-name
-                                    :x-waiter-cmd (kitchen-cmd "-p $PORT0")
-                                    :x-waiter-max-instances 1}))
-          {:keys [cookies service-id] :as response} (make-successful-request waiter-url request-headers)
-          _ (assert-response-status response 200)
-          router-id->router-url (routers waiter-url)
+(deftest ^:parallel ^:integration-slow test-request-queue-timeout-max-instances-limit
+  ;; Limits the service to a single instance and then makes a long requests to it on each router.
+  ;; Then we make a request with a small timeout and make sure it actually times out.
+  (testing-using-waiter-url
+    (let [router-id->router-url (routers waiter-url)
           num-routers (count router-id->router-url)
-          started-latch (CountDownLatch. num-routers)
-          completed-latch (CountDownLatch. num-routers)]
-      (doseq [[router-id router-url] (seq router-id->router-url)] ; make multiple requests to disable work-stealing
-        (let [request-cid-success (str service-name "-success." router-id)]
-          (async/thread
-            (log/info "starting long request" request-cid-success "for" long-request-period-ms "ms at" router-url)
-            (.countDown started-latch)
-            (try
-              (assert-response-status
-                (make-successful-request router-url
-                                         (assoc request-headers
-                                           :x-cid request-cid-success
-                                           :x-kitchen-delay-ms long-request-period-ms)
-                                         :cookies cookies)
-                200)
-              (log/info "long request" request-cid-success "complete")
-              (catch Exception e
-                (log/error e "long request" request-cid-success "encountered error")
-                (is false (str e))))
-            (.countDown completed-latch))))
-      (log/info "awaiting long request(s) to start...")
-      (.await started-latch)
-      (Thread/sleep 1000)
-      (let [request-cid-timeout (str service-name "-timeout")
-            request-headers (assoc request-headers
-                              :x-cid request-cid-timeout
-                              :x-waiter-queue-timeout (time/in-millis (time/seconds timeout-period-sec)))
-            start-time-ms (System/currentTimeMillis)]
-        (log/info "making request" request-cid-timeout "that is expected to timeout")
-        (let [{:keys [body service-name] :as response} (make-request-verbose waiter-url request-headers cookies)]
+          long-request-period-ms (* 3 5000)
+          long-request-started-latch (CountDownLatch. num-routers)
+          long-request-ended-latch (CountDownLatch. num-routers)
+          make-request-fn (fn make-request-fn [target-url extra-headers cookies]
+                            (make-request-with-debug-info
+                              extra-headers #(make-kitchen-request target-url % :cookies cookies)))
+          extra-headers {:x-waiter-cmd (kitchen-cmd "-p $PORT0")
+                         :x-waiter-concurrency-level num-routers
+                         :x-waiter-max-instances 1
+                         :x-waiter-name (rand-name)}
+          {:keys [cookies instance-id service-id] :as response} (make-request-fn waiter-url extra-headers nil)]
+      (assert-response-status response 200)
+      (log/info "canary instance-id:" instance-id)
+      (with-service-cleanup
+        service-id
+        (doseq [[_ router-url] (seq router-id->router-url)]
+          (launch-thread
+            (.countDown long-request-started-latch)
+            (let [extra-headers (assoc extra-headers :x-kitchen-delay-ms long-request-period-ms)
+                  response (make-request-fn router-url extra-headers cookies)]
+              (assert-response-status response 200)
+              (log/info "long request instance-id:" (:instance-id response))
+              (is (= instance-id (:instance-id response))))
+            (.countDown long-request-ended-latch)))
+        (.await long-request-started-latch)
+        (let [timeout-period-ms (/ long-request-period-ms 3)
+              timeout-period-secs (-> timeout-period-ms t/millis t/in-seconds)
+              extra-headers (assoc extra-headers :x-waiter-queue-timeout timeout-period-ms)
+              _ (Thread/sleep timeout-period-ms)
+              {:keys [body] :as response} (make-request-fn waiter-url extra-headers cookies)]
           (assert-response-status response 503)
-          (assert-failed-request service-name body start-time-ms timeout-period-sec false)))
-      (log/info "awaiting long request(s) to complete...")
-      (.await completed-latch)
-      (delete-service waiter-url service-id))))
+          (is (str/includes?
+                (str body)
+                (str "After " timeout-period-secs " seconds, no instance available to handle request.")))
+          (is (str/includes? (str body) service-id))
+          (is (str/blank? (:instance-id response))))
+        (.await long-request-ended-latch)))))

 (deftest ^:parallel ^:integration-fast test-grace-period-with-tokens
   (testing-using-waiter-url
-    (let [grace-period (time/minutes 2)
+    (let [grace-period (t/minutes 2)
           token (rand-name)]
       (try
         (log/info "Creating token for" token)
         (let [{:keys [status body]}
-              (post-token waiter-url {:cmd (kitchen-cmd (str "-p $PORT0 " (time/in-millis grace-period)))
+              (post-token waiter-url {:cmd (kitchen-cmd (str "-p $PORT0 " (t/in-millis grace-period)))
                                       :version "not-used"
                                       :cpus 1
                                       :mem 1024
@@ -216,7 +192,7 @@
                                       :permitted-user "*"
                                       :token token
                                       :name (str "test" token)
-                                      :grace-period-secs (time/in-seconds grace-period)
+                                      :grace-period-secs (t/in-seconds grace-period)
                                       :cmd-type "shell"})]
           (is (= 200 status) (str "Did not get a 200 response. " body)))
         (log/info "Making request for" token)
@@ -226,7 +202,7 @@
           (is (= 200 status) (str "Did not get a 200 response. " body))
           (when (and (= 200 status) (can-query-for-grace-period? waiter-url))
             (log/info "Verifying app grace period for" token)
-            (is (= (time/in-seconds grace-period) (service-id->grace-period waiter-url service-id))))
+            (is (= (t/in-seconds grace-period) (service-id->grace-period waiter-url service-id))))
           (delete-service waiter-url service-id))
         (finally
           (delete-token-and-assert waiter-url token))))))


checkpoint

checkpoint

--- src-cljs/app/main.cljs
+++ src-cljs/app/main.cljs
@@ -9,7 +9,8 @@
 ;;------------------------------------------------------------------------------

 (def snapshot-list (atom nil))
-(def current-index (atom nil))
+(def snapshot-index (atom nil)) ; can this be derived from current time, quickly?
+(def selected-time (atom nil))
 (def url-update-timout (atom nil)) ; This probably doesn't need to be atom, maybe be clojure feature that handles this

 ;;------------------------------------------------------------------------------
@@ -53,6 +54,37 @@
         [:td (build-decrement-btn "decrement-minute")]
         (build-nbsp-cell)
         [:td (build-decrement-btn "toggle-meridian")]]]]])
+
+(defn pad [num]
+  "zero pad timepicker digits"
+  (format "%02d" num))
+
+;;------------------------------------------------------------------------------
+;; Watchers
+;;------------------------------------------------------------------------------
+
+(defn on-snapshot-index-change [_ _ _ new-index]
+  (let [snapshot (@snapshot-list new-index)
+        time (Date. (:time snapshot))
+        image (:image snapshot)
+        time-display (str (.toDateString time) " " (.toLocaleTimeString time))]
+    (attr ($ "#currentSnapshot") "src" image)
+    (text ($ "#imageDateTime") time-display)
+    (prop ($ "#earlier") "disabled" (= (inc new-index) (count @snapshot-list)))
+    (prop ($ "#later") "disabled" (zero? new-index))))
+
+(add-watch snapshot-index :_ on-snapshot-index-change)
+
+(defn on-selected-time-change [_ _ _ new-time]
+  (let [hour (.getHours new-time)
+        meridian (if (> 11 hour) "PM" "AM")
+        hour (if (> 12 hour) (- hour 12) hour)]
+    (val ($ "#hour") (pad hour))
+    (val ($ "#minute") (pad (.getMinutes new-time)))
+    (val ($ "#meridian") meridian)
+    (.datepicker ($ "#datepicker") "update" new-time)))
+
+(add-watch timestamp :_ on-selected-time-change)

 ;;------------------------------------------------------------------------------
 ;; Events
@@ -105,10 +137,10 @@
       (js->clj)
       (clojure.walk/keywordize-keys)))))

-(defn init-current-index []
+(defn init-snapshot-index []
   (let [image (attr ($ "#currentSnapshot") "src")
-        starting-index (first (keep-indexed #(if (= image %2) %1) @snapshot-list))]
-    (swap! current-index #(if (pos? starting-index)
+        starting-index (first (keep-indexed #(if (= image (:image %2)) %1) @snapshot-list))]
+    (swap! snapshot-index #(if (pos? starting-index)
                                 starting-index
                                 0))))

@@ -116,7 +148,7 @@
   (init-datepicker)
   (init-timepicker) ; seperate namespace?
   (init-snapshot-list)
-  (init-current-index) ; current-index change is probably what replaces original update
+  (init-snapshot-index) ; current-index change is probably what replaces original update
   (add-events))

 (document-ready init)


Only fetch documents with a local copy.

Only fetch documents with a local copy.

--- src-cljs/pepa/api.cljs
+++ src-cljs/pepa/api.cljs
@@ -254,14 +254,13 @@

 (defmulti ^:private entities-changed* (fn [state entity changes]
                                         entity))
-
-(comment
-  ;; Called like:
-  (entities-changed* :documents {:pages #{3 4 5}
-                                 :documents #{1 2 3}}))
+(defmethod entities-changed* :default [& _])

 (defmethod entities-changed* :documents [state _ changes]
-  (fetch-documents! (:documents changes)))
+  ;; Only fetch documents with a local copy
+  (let [ids (filter #(get-in @state [:documents %])
+                    (:documents changes))]
+    (fetch-documents! ids)))

 (defmethod entities-changed* :inbox [state _ changes]
   (go
@@ -272,7 +271,9 @@
           ;; TODO: Apply the changes to the Inbox
           (js/console.warn "Not applying changes to Inbox: Not implemented"))))))

-(defmethod entities-changed* :default [& _])
+;;; HACK
+(defmethod entities-changed* :deletions [state _ changes]
+  (js/console.warn "NOT applying deletions: Not implemented"))

 (defn entities-changed! [state changes]
   (doseq [entity (keys changes)]


Better Device Tab and Table.

Better Device Tab and Table.

Fix #328 Typo in error-handler in devices.cljs

Remove API metadata from view

Fix #331

Better labelling of fields.

name -> further description,
description -> unique descrption

Move device_id to end of table.

Tidy up add and edit forms.

Add underlying sensor types to device table.

Fix #327 Hide add device button when appropriate.

--- src-cljs/kixi/hecuba/tabs/hierarchy/devices.cljs
+++ src-cljs/kixi/hecuba/tabs/hierarchy/devices.cljs
@@ -79,9 +79,9 @@

 (defn error-handler [event-chan]
   (fn [{:keys [status status-text]}]
-    (put! event-chan {:path :event :value {:status true
-                                           :class "alert alert-danger"
-                                           :text status-text}})))
+    (put! event-chan {:event :alert :value {:status true
+                                            :class "alert alert-danger"
+                                            :text status-text}})))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Adding new sensor
@@ -212,9 +212,9 @@
                                      (put! event-chan {:event :editing :value false}))} "Cancel"]]]
               [:h3 "Device"]
               (static-text cursor :device_id "Device ID")
-              (text-input-control cursor owner [:device] :name "Parent Device Name")
+              (static-text cursor :description "Unique Description")
+              (text-input-control cursor owner [:device] :name "Further Description")
               (location-input cursor owner)
-              (static-text cursor :metadata "API User Metadata")
               (bs/checkbox cursor owner :device :privacy "Private")
               [:h3 "Sensors"]
               (let [sensors (remove #(:synthetic %) (:readings cursor))]
@@ -281,9 +281,9 @@
                         :onClick (fn [_]
                                    (put! event-chan {:event :adding-device :value false}))}
                "Cancel"]]]
-            (bs/text-input-control cursor owner :device :description "Description" true)
+            (bs/text-input-control cursor owner :device :description "Unique Description" true)
+            (bs/text-input-control cursor owner :device :name "Further Description")
             (location-input cursor owner)
-            (bs/text-input-control cursor owner :device :name "Name")
             (bs/checkbox cursor owner :device :privacy "Private")]]]
          [:div.col-md-12
           [:h3 "Create sensor:"]
@@ -306,19 +306,19 @@
       (render [_]
         (html
          (let [{:keys [description privacy location name
-                       device_id editable metadata privacy]} cursor
+                       device_id editable privacy]} cursor
                        devices   (:devices properties)
                        selected? (= (:selected devices) device_id)]
            [:tr {:onClick (fn [_] (om/update! devices :selected (if selected? nil device_id)))
                  :class (when selected? "success")
                  :id (str table-id "-selected")}
             [:td description]
-            [:td device_id]
+            [:td name]
             [:td (common/location-col location)]
-            [:td metadata]
-            [:td name]
             [:td (privacy-label privacy)]
-            [:td (count (filter #(not (:synthetic %)) (:readings cursor)))]]))))))
+            [:td (count (filter #(not (:synthetic %)) (:readings cursor)))]
+            [:td (string/join ", " (mapv :type (filter #(not (:synthetic %)) (:readings cursor))))]
+            [:td device_id]]))))))

 (defn devices-table [editing-chan properties]
@@ -353,13 +353,13 @@
             [:table {:class "table table-hover table-condensed"}
              [:thead
               [:tr
-               (sorting-th owner "Description" :description)
-               (sorting-th owner "Device ID" :device_id)
+               (sorting-th owner "Unique Description" :description)
+               (sorting-th owner "Further Description" :name)
                (sorting-th owner "Location" :location)
-               (sorting-th owner "Metadata" :metadata)
-               (sorting-th owner "Name" :name)
                (sorting-th owner "Privacy" :privacy)
-               (sorting-th owner "No. of Sensors" :count)]]
+               (sorting-th owner "No. of Sensors" :count)
+               (sorting-th owner "Sensor Types" :sensor_types)
+               (sorting-th owner "Device ID" :device_id)]]
              [:tbody
               (for [row (if sort-asc
                           (sort-by sort-key devices)
@@ -406,13 +406,14 @@
           [:div.btn-toolbar
            ;; Add new device
            [:button {:type "button"
-                     :class (str "btn btn-primary " (when-not (and (not adding-sensor)
-                                                                   (not adding-device)
-                                                                   (not editing)
-                                                                   (:editable property))))
+                     :class (str "btn btn-primary " (when (or adding-sensor
+                                                              adding-device
+                                                              editing
+                                                              (not (:editable property)))
+                                                      "hidden"))
                      :onClick (fn [_]
                                 (om/update! properties [:devices :adding-device] true))}
-            "Add new device"]
+            [:div {:class "fa fa-plus"} " Add device"]]
            ;; Edit device
            [:button {:type "button"
                      :class (str "btn btn-primary " (when-not (and (not adding-sensor)


* src/clj/cljs/core.clj: optimize satisfies?

--- src/clj/cljs/core.clj
+++ src/clj/cljs/core.clj
@@ -175,6 +175,11 @@
 (defmacro bit-and
   ([x y] (list 'js* "(~{} & ~{})" x y))
   ([x y & more] `(bit-and (bit-and ~x ~y) ~@more)))
+
+;; internal do not use
+(defmacro unsafe-bit-and
+  ([x y] (bool-expr (list 'js* "(~{} & ~{})" x y)))
+  ([x y & more] `(unsafe-bit-and (unsafe-bit-and ~x ~y) ~@more)))

 (defmacro bit-or
   ([x y] (list 'js* "(~{} | ~{})" x y))
@@ -518,9 +523,10 @@
         msym (symbol "-__protocol_mask")]
     `(let [~xsym ~x]
        (if (and (coercive-not= ~xsym nil)
-                ~@(if-let [bit (fast-path-protocols p)]
-                    [(bool-expr `(bit-and (. ~xsym ~msym) ~bit))])
-                ~(bool-expr `(. ~xsym ~(symbol (core/str "-" prefix)))))
+                (or
+                 ~(if-let [bit (fast-path-protocols p)]
+                    `(unsafe-bit-and (. ~xsym ~msym) ~bit))
+                 ~(bool-expr `(. ~xsym ~(symbol (core/str "-" prefix))))))
          true
          (cljs.core/type_satisfies_ ~psym ~xsym)))))


Prevent the a card from queueing the same prompt

multiple times

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -242,7 +242,11 @@
   ([state side card msg choices f] (show-prompt state side card msg choices f nil))
   ([state side card msg choices f {:keys [priority prompt-type show-discard] :as args}]
    (let [prompt (if (string? msg) msg (msg state side card nil))]
-     (when (or (:number choices) (#{:credit :counter} choices) (> (count choices) 0))
+     (when (and (or (:number choices) (#{:credit :counter} choices) (> (count choices) 0))
+                (or (nil? card)
+                    (empty? (->> (get-in @state [side :prompt])
+                                 (map #(vec [(get-in % [:card :cid]) (:msg %)]))
+                                 (filter #(= % (vec [(:cid card) msg])))))))
        (swap! state update-in [side :prompt]
               (if priority
                 #(cons {:msg prompt :choices choices :effect f :card card


hide collections

hide collections

--- src/clj/hsm/views.clj
+++ src/clj/hsm/views.clj
@@ -100,7 +100,7 @@
                 [:div.navbar-collapse.collapse
                  [:ul.nav.navbar-nav
                   [:li [:a {:href "/users"} "Users"]]
-                  [:li [:a {:href "/collections"} "Collections"]]
+                  ; [:li [:a {:href "/collections"} "Collections"]]
                   [:li [:a {:href "/discussions"} "Discussions"]]
                    [:li.dropdown
                      [:a.dropdown-toggle {:data-toggle "dropdown" :href "#"} "Platforms" [:span.caret]]


Share checksum address in wallet

Share checksum address in wallet

Signed-off-by: Serhy <2afeee62f16dcab4f5fa80c3a205f450766eb876@status.im>

--- src/status_im/ui/screens/wallet/request/views.cljs
+++ src/status_im/ui/screens/wallet/request/views.cljs
@@ -86,7 +86,7 @@
       [toolbar/actions [{:icon      :main-icons/share
                          :icon-opts {:color               :white
                                      :accessibility-label :share-button}
-                         :handler   #(list-selection/open-share {:message address-hex})}]]]
+                         :handler   #(list-selection/open-share {:message (eip55/address->checksum address-hex)})}]]]
      [react/view {:flex 1}
       [common/network-info {:text-color :white}]
       [qr-code-viewer/qr-code-viewer


Move xorp to use 'primary_interface'

Move xorp to use 'primary_interface'

xorp should adhere to the standard we have set which is to use
primary_interface when referencing (unsurprisingly) your primary
interface.

--- roles/neutron-data-network/templates/etc/xorp/config.boot
+++ roles/neutron-data-network/templates/etc/xorp/config.boot
@@ -1,6 +1,6 @@
 interfaces {
     restore-original-config-on-shutdown: false
-    interface eth0 {
+    interface {{ hostvars[inventory_hostname][primary_interface]['device'] }} {
         description: "Internal pNodes interface"
         disable: false
         default-system-config
@@ -10,8 +10,8 @@
 protocols {
     igmp {
         disable: false
-        interface eth0 {
-            vif eth0 {
+        interface {{ hostvars[inventory_hostname][primary_interface]['device'] }} {
+            vif {{ hostvars[inventory_hostname][primary_interface]['device'] }} {
                 disable: false
                 version: 3
             }


Joe closes #27 multiple displays of the same project bug. New call to clj-cctray lib required

--- src/nevergreen/api.clj
+++ src/nevergreen/api.clj
@@ -1,15 +1,19 @@
 (ns nevergreen.api
   (:require [clj-cctray.core :as parser]
             [clj-cctray.filtering :as filtering]
+            [clj-cctray.ci.go-snap :as go]
             [cheshire.core :refer [generate-string]]
             [environ.core :refer [env]]
             [nevergreen.config :refer :all]
             [compojure.core :refer :all]))

 (defn get-all-projects [url]
-  (parser/get-projects url :options [:go :normalise]))
+  (->>
+    (parser/get-projects url :options [:go :normalise])
+    (go/distinct-projects)))

 (defn get-interesting-projects [params]
   (->> (parser/get-projects (:cctray params) :options [:go :normalise])
+       (go/distinct-projects)
        (filtering/interesting)
        (filtering/by-name (:includedProjects params))))


Reduce number of windowing crashes

Reduce number of windowing crashes

--- test/onyx/windowing/basic_windowing_crash_test.clj
+++ test/onyx/windowing/basic_windowing_crash_test.clj
@@ -71,17 +71,11 @@
   (when-not (= :job-completed event-type)
     (swap! test-state conj [[lower-bound upper-bound] group-key extent-state])))

-(def crashed? (atom false))
-
 (def identity-crash
   {:lifecycle/handle-exception restartable?
    :lifecycle/after-read-batch (fn [event lifecycle]
-                                 (when (or (and (some #(= (:id %) 16)
-                                                      (:onyx.core/batch event))
-                                                (not @crashed?))
-                                           (zero? (rand-int 100)))
-                                   (println "CRASH IT")
-                                   (reset! crashed? true)
+                                 (when (and (not (empty? (:onyx.core/batch event)))
+                                                (zero? (rand-int 6)))
                                   (throw (ex-info "Restart me!" {})))
                                  {})})


CMR-7572: Preview gem commit ref update (#1283)

--- collection-renderer-lib/project.clj
+++ collection-renderer-lib/project.clj
@@ -12,7 +12,7 @@
   {:repo "https://git.earthdata.nasa.gov/scm/cmr/cmr_metadata_preview.git"
    :version "cmr_metadata_preview-0.2.9"
    :commit-id (or (System/getenv "CMR_METADATA_PREVIEW_COMMIT")
-                  "3b38eced538")})
+                  "a63c41cadfa")})

 (def gem-install-path
   "The directory within this library where Ruby gems are installed."


Update agent to make more 'production-ready'.

--- metlog-agent/src/metlog_agent/core.clj
+++ metlog-agent/src/metlog_agent/core.clj
@@ -9,26 +9,46 @@

 (def start-t (System/currentTimeMillis))

+(def sensor-result-queue (java.util.concurrent.LinkedBlockingQueue.))
+
+(defn sensor-reading [ series-name val ]
+  {:t (java.util.Date.)
+   :series_name series-name
+   :val val})
+
+(defn enqueue-sensor-reading [ reading ]
+  (log/info "enquing sensor reading" reading)
+  (.add sensor-result-queue reading))
+
 (defn poll-sensor-1 []
-  {:t (java.util.Date.)
-   :series_name "sine"
-   :val (Math/sin (/ (- (System/currentTimeMillis) start-t) 250.0))})
+  (enqueue-sensor-reading
+   (sensor-reading "sine" (Math/sin (/ (- (System/currentTimeMillis) start-t) 60000.0)))))

 (defn poll-sensor-2 []
-  {:t (java.util.Date.)
-   :series_name "cosine"
-   :val (Math/cos (/ (- (System/currentTimeMillis) start-t) 250.0))})
+  (enqueue-sensor-reading
+   (sensor-reading "cosine" (Math/cos (/ (- (System/currentTimeMillis) start-t) 60000.0)))))

-(def sensor-result-queue (java.util.concurrent.LinkedBlockingQueue.))
+(defn poll-w1-sensor [ path]
+  (with-open [rdr (clojure.java.io/reader path)]
+  (let [ line (second (line-seq rdr)) ]
+    (if (not (nil? line))
+      (enqueue-sensor-reading
+       (sensor-reading "basement-temp"
+        (/ (Double/valueOf (.substring line 29)) 1000.0)))))))

 (defn poll-sensors []
   (log/debug "poll-sensors")
   (locking sensor-result-queue
-    (.add sensor-result-queue (poll-sensor-1))
-    (.add sensor-result-queue (poll-sensor-2))))
+    (poll-sensor-1)
+    (poll-sensor-2)
+    (if-let [ sensor-path (config-property "sensor.path") ]
+      (poll-w1-sensor sensor-path))))

 (defn do-update [ snapshot ]
-  (client/post "http://localhost:8080/data" { :body (pr-str snapshot)}))
+  (let [url (config-property "vault.url" "http://localhost:8080/data")
+        data { :body (pr-str snapshot)}]
+    (log/info "Posting" data " to " url)
+    (client/post url data)))

 (defn update-vault []
   (log/debug "update-vault")
@@ -40,8 +60,8 @@
 (defn -main
   "I don't do a whole lot ... yet."
   [& args]
-  (at-at/every 1000 (exception-barrier poll-sensors) my-pool)
-  (at-at/every 5000 (exception-barrier update-vault) my-pool)
+  (at-at/every 15000 (exception-barrier poll-sensors) my-pool)
+  (at-at/every 60000 (exception-barrier update-vault) my-pool)
   (println "Running."))


Navigate back to home after upload is finished


recovery onboarding [#4498] [#4483]

recovery onboarding [#4498] [#4483]

--- src/status_im/ui/screens/accounts/recover/events.cljs
+++ src/status_im/ui/screens/accounts/recover/events.cljs
@@ -40,7 +40,8 @@
                      :signed-up?            true
                      :signing-phrase        phrase
                      :settings              (constants/default-account-settings)
-                     :wallet-set-up-passed? true}]
+                     :wallet-set-up-passed? false
+                     :seed-backed-up?       true}]
      (when-not (string/blank? public-key)
        (-> db
            (accounts-events/add-account account)


removed to-array method

removed to-array method

--- src/ontrail/weekly.clj
+++ src/ontrail/weekly.clj
@@ -69,7 +69,6 @@
       kw-sport-distance (acc kw-sport-distance :distance)
       kw-sport-duration (acc kw-sport-duration :duration))))

-(defn to-array [sum] nil)

 (defn weekly-sums [results]
   (if (>= (count results) 1)


Hotfix, close #38

Hotfix, close #38

--- frontend/src/cruncher/views.cljs
+++ frontend/src/cruncher/views.cljs
@@ -95,7 +95,7 @@
                                            (vlib/sortable-table-header :individual_stamina "IV Stamina")))
                         (apply dom/tbody nil
                                (map #(poketable-entry (lib/merge-react-key %)) (lib/inventory-pokemon))))
-             (let [jquery (js* "$")]
+             #_(let [jquery (js* "$")]
                (.stickyTableHeaders (jquery "#poketable"))))))
 (def poketable (om/factory PokeTable {}))


Show example with macroexpand

Show example with macroexpand

--- src/clojure/clojure_walkthrough/cjia/ch07_xx.clj
+++ src/clojure/clojure_walkthrough/cjia/ch07_xx.clj
@@ -234,3 +234,4 @@

 (assert-true (< (* 4 5) (* 2 5))) ;; java.lang.RuntimeException
                                   ;; (* 4 5) is not < 10
+(macroexpand-1 '(assert-true (>= (* 2 4) (/ 18 2)))) ;; (clojure.core/let [rhsv__20666__auto__ (/ 18 2) ret__20667__auto__ (>= (* 2 4) (/ 18 2))] (clojure.core/if-not ret__20667__auto__ (throw (java.lang.RuntimeException. (clojure.core/str (quote (* 2 4)) " is not " (quote >=) " " rhsv__20666__auto__))) true))


Misc fixes, most tests now passing

Misc fixes, most tests now passing

--- src/main/clj/clojure/core/matrix/complex.clj
+++ src/main/clj/clojure/core/matrix/complex.clj
@@ -17,7 +17,7 @@
 ;;
 ;; The ComplexArray class and protocol implementations
 ;;
-;; Implemented as a wrapper of two numerical arrays representing the real and imaginary parts
+;; Implemented as a wrapper of two real-valued numerical arrays representing the real and imaginary parts

 (declare my-det)
 (deftype ComplexArray [real imag]
@@ -59,6 +59,15 @@
   (get-nd [m indexes]
     (c/complex (double (mp/get-nd (.real m) indexes))
                (double (mp/get-nd (.imag m) indexes))))
+
+  mp/PZeroDimensionAccess
+  (get-0d
+    [m]
+    (c/complex (mp/get-0d (.real m)) (mp/get-0d (.imag m))))
+  (set-0d!
+    [m v]
+    (mp/set-0d! (.real m) (clojure.core.matrix.complex/real v))
+    (mp/set-0d! (.imag m) (clojure.core.matrix.complex/imag v)))

   mp/PIndexedSetting
   (set-1d [m row v]
@@ -92,6 +101,11 @@
   (toString [m]
     (str "#complex/complex-array [" (clojure.core.matrix.complex/real m) ", " (clojure.core.matrix.complex/imag m) "]"))

+  mp/PReshaping
+  (reshape [m shape]
+    (ComplexArray. (mp/reshape real shape)
+                   (mp/reshape imag shape)))
+
   Seqable
   (seq [m]
     (map complex-array (m/slices (.real m)) (m/slices (.imag m))))


Whitespace

Whitespace

--- src/oxcart/pattern.clj
+++ src/oxcart/pattern.clj
@@ -20,6 +20,7 @@
 ;;  make core.match a dependency of this project rather than hard
 ;;  coding datastructure dependant paths and equality checks.

+
 (defn def?
   "λ AST -> Boolean


Handle case where blog-prefix is blank (#203)

--- src/leiningen/new/cryogen/src/cryogen/server.clj
+++ src/leiningen/new/cryogen/src/cryogen/server.clj
@@ -34,7 +34,9 @@
                        :no-trailing-slash (if (or (= req-uri "")
                                                   (= req-uri "/")
                                                   (= req-uri
-                                                     (.substring blog-prefix 1)))
+                                                     (if (string/blank? blog-prefix)
+                                                       blog-prefix
+                                                       (.substring blog-prefix 1))))
                                             (path req-uri "index.html")
                                             (path (str req-uri ".html")))
                        :dirty (path (str req-uri ".html")))