clean up

clean up

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -13,27 +13,21 @@
 ;; -------------------------
 ;; Re-frame data

-<<<<<<< HEAD
-=======
 (re-frame/register-sub        ;; a new subscription handler
    :phones             ;; usage (subscribe [:phones])
    (fn [db]
      (reaction (:phones @db))))  ;; pulls out :phones

->>>>>>> 14a2a55... bump up to re-frame 0.2.0
 (re-frame/register-sub
  :search-input
  (fn [db]
    (reaction (:search-input @db))))

-<<<<<<< HEAD
 (re-frame/register-sub        ;; a new subscription handler
  :phones             ;; usage (subscribe [:phones])
  (fn [db]
    (reaction (:phones @db))))  ;; pulls out :phones

-=======
->>>>>>> 14a2a55... bump up to re-frame 0.2.0
 (re-frame/register-sub
  :selected-image-url
  (fn [db [_ phone-id]]
@@ -95,6 +89,29 @@
                    :response-format :json
                    :keywords? true})
    app-state))
+
+(re-frame/register-handler
+ :process-phone-detail-response
+ (fn
+   [app-state [_ [phone-id response]]]
+   (assoc-in app-state [:phone-details (keyword phone-id)] response)))
+
+(re-frame/register-handler
+ :process-phone-detail-bad-response
+ (fn
+   [app-state [_ [phone-id response]]]
+   (println "Error getting phone detail for id: " phone-id)
+   app-state))
+
+(re-frame/register-handler
+ :load-phone-detail
+ (fn
+   [app-state [_ phone-id]]
+   (ajax/GET (str "phones/" phone-id ".json")
+             {:handler #(re-frame/dispatch [:process-phone-detail-response [phone-id %1]])
+              :error-handler #(re-frame/dispatch [:process-phone-detail-bad-response [phone-id %1]])
+              :response-format :json
+              :keywords? true})))

 (re-frame/register-handler
  :process-phone-detail-response


Need MOAR LOGGING

Need MOAR LOGGING

--- src/clojure_lambda_skeleton/core.clj
+++ src/clojure_lambda_skeleton/core.clj
@@ -17,5 +17,6 @@
   (let [logger (.getLogger context)
         request (parse-stream (reader input))]
     (.log logger (str "request: " (generate-string request)))
+    (.log logger "MOAR LOGGING!!")
     (.log logger (str "a=" (query-param request "a")))))


sometimes IOExceptions do occur and they're useless, swallow them

--- src/subrosa/netty.clj
+++ src/subrosa/netty.clj
@@ -49,7 +49,7 @@
         (when (= :client-disconnect (:type condition))
           (println "Tried to grab data about a client after disconnect.")))
       (when (not (some #{(class (.getCause evt))}
-                       #{;java.io.IOException
+                       #{java.io.IOException
                          java.nio.channels.ClosedChannelException}))
         (println up-or-down "ERROR")
         (.printStackTrace (.getCause evt)))))


Improve condtion and table interface on dsl.

--- src/suricatta/dsl.clj
+++ src/suricatta/dsl.clj
@@ -14,13 +14,16 @@
   (field* [_] "Field constructor"))

 (defprotocol ITable
-  (table [_] "Table constructor"))
+  (table* [_] "Table constructor"))

 (defprotocol IName
   (name [_] "Name constructor"))

+(defprotocol IOnStep
+  (on [_ conditions]))
+
 (defprotocol ICondition
-  (condition [_] "Condition constructor"))
+  (condition* [_] "Condition constructor"))

 (defprotocol IVal
   (val [_] "Val constructor"))
@@ -39,21 +42,18 @@
   org.jooq.Field
   (field* [f] f)

-  ;; org.jooq.impl.SelectQueryAsExistsCondition
-  ;; (field* [f] f)
-
   org.jooq.impl.Val
   (field* [v] v))

 (extend-protocol ITable
   java.lang.String
-  (table [s] (DSL/table s))
+  (table* [s] (DSL/table s))

   clojure.lang.Keyword
-  (table [kw] (table (clojure.core/name kw)))
+  (table* [kw] (table* (clojure.core/name kw)))

   org.jooq.Table
-  (table [t] t))
+  (table* [t] t))

 (extend-protocol IName
   java.lang.String
@@ -66,16 +66,16 @@

 (extend-protocol ICondition
   java.lang.String
-  (condition [s] (DSL/condition s))
+  (condition* [s] (DSL/condition s))

   org.jooq.impl.CombinedCondition
-  (condition [c] c)
+  (condition* [c] c)

   org.jooq.impl.SQLCondition
-  (condition [c] c)
+  (condition* [c] c)

   clojure.lang.PersistentVector
-  (condition [v]
+  (condition* [v]
     (let [sql    (first v)
           params (rest v)]
       (->> (into-array Object params)
@@ -92,6 +92,13 @@
 (defn field
   [data & {:keys [alias] :as opts}]
   (let [f (field* data)]
+    (if alias
+      (.as f (clojure.core/name alias))
+      f)))
+
+(defn table
+  [data & {:keys [alias] :as opts}]
+  (let [f (table* data)]
     (if alias
       (.as f (clojure.core/name alias))
       f)))
@@ -148,15 +155,17 @@
   (.join q t))

 (defn on
-  [q cond]
-  (.on q cond))
+  [q & clauses]
+  (->> (map condition* clauses)
+       (into-array org.jooq.Condition)
+       (.on q)))

 (defn where
   "Create where clause with variable number
   of conditions (that are implicitly combined
   with `and` logical operator)."
   [q & clauses]
-  (->> (map condition clauses)
+  (->> (map condition* clauses)
        (into-array org.jooq.Condition)
        (.where q)))

@@ -193,7 +202,7 @@
 (defn and
   "Logican operator `and`."
   [& conditions]
-  (let [conditions (map condition conditions)]
+  (let [conditions (map condition* conditions)]
     (reduce (fn [acc v] (.and acc v))
             (first conditions)
             (rest conditions))))
@@ -201,7 +210,7 @@
 (defn or
   "Logican operator `or`."
   [& conditions]
-  (let [conditions (map condition conditions)]
+  (let [conditions (map condition* conditions)]
     (reduce (fn [acc v] (.or acc v))
             (first conditions)
             (rest conditions))))


[#2183] Adapt schema to null values

[#2183] Adapt schema to null values

--- backend/specs/akvo/lumen/specs/transformation.clj
+++ backend/specs/akvo/lumen/specs/transformation.clj
@@ -236,7 +236,7 @@
 (s/def ::transformation.derive-category/target (s/keys
                                                :req-un [::transformation.derive-category.target/column]))

-(s/def ::transformation.derive-category.derivation.text/mappings (s/coll-of (s/tuple (s/coll-of string? :kind vector? :min-count 1) string?) :kind vector? :min-count 1))
+(s/def ::transformation.derive-category.derivation.text/mappings (s/coll-of (s/tuple (s/coll-of (s/nilable string?) :kind vector? :min-count 1) string?) :kind vector? :min-count 1))

 (s/def ::transformation.derive-category.derivation.number/op #{">" "<" ">=" "<=" "="})


[#2472] Adapt/fix geo-point tx

[#2472] Adapt/fix geo-point tx

--- backend/src/akvo/lumen/lib/transformation/geo.clj
+++ backend/src/akvo/lumen/lib/transformation/geo.clj
@@ -25,35 +25,37 @@

 (defmethod engine/apply-operation "core/generate-geopoints"
   [{:keys [tenant-conn]} table-name columns op-spec]
-  (let [{:strs [columnNameLat columnNameLong columnTitleGeo]} (engine/args op-spec)
-        get-client-type (partial engine/column-type columns)
-        column-types (map get-client-type [columnNameLat columnNameLong])]
-    (if (every? #(= "number" %) column-types)
-      (try
-        (let [column-name-geo (engine/next-column-name columns)
-              opts {:table-name table-name :column-name-geo column-name-geo}]
-          (jdbc/with-db-transaction [conn tenant-conn]
-            (db.tx.geo/add-geometry-column conn opts)
-            (add-index conn table-name column-name-geo)
-            (db.tx.geo/generate-geopoints conn (conj opts {:column-name-lat columnNameLat
-                                                 :column-name-long columnNameLong})))
-          (jdbc/execute! tenant-conn "DEALLOCATE ALL")
-          {:success? true
-           :execution-log [(format "Generated geopoints for %s" table-name)]
-           :columns (conj columns {"title" columnTitleGeo
-                                   "type" "geopoint"
-                                   "sort" nil
-                                   "hidden" false
-                                   "direction" nil
-                                   "columnName" column-name-geo})})
-        (catch Exception e
-          (log/debug e)
-          {:success? false
-           :message (.getMessage e)}))
-      (let [msg "Selected columns are not all numeric"]
-        (log/debug msg)
-        {:success? false
-         :message msg}))))
+  (if-let [response-error (engine/column-title-error? (get (engine/args op-spec) "columnTitleGeo") columns)]
+    response-error
+   (let [{:strs [columnNameLat columnNameLong columnTitleGeo]} (engine/args op-spec)
+         get-client-type (partial engine/column-type columns)
+         column-types (map get-client-type [columnNameLat columnNameLong])]
+     (if (every? #(= "number" %) column-types)
+       (try
+         (let [column-name-geo (engine/next-column-name columns)
+               opts {:table-name table-name :column-name-geo column-name-geo}]
+           (jdbc/with-db-transaction [conn tenant-conn]
+             (db.tx.geo/add-geometry-column conn opts)
+             (add-index conn table-name column-name-geo)
+             (db.tx.geo/generate-geopoints conn (conj opts {:column-name-lat columnNameLat
+                                                            :column-name-long columnNameLong})))
+           (jdbc/execute! tenant-conn "DEALLOCATE ALL")
+           {:success? true
+            :execution-log [(format "Generated geopoints for %s" table-name)]
+            :columns (conj columns {"title" columnTitleGeo
+                                    "type" "geopoint"
+                                    "sort" nil
+                                    "hidden" false
+                                    "direction" nil
+                                    "columnName" column-name-geo})})
+         (catch Exception e
+           (log/debug e)
+           {:success? false
+            :message (.getMessage e)}))
+       (let [msg "Selected columns are not all numeric"]
+         (log/debug msg)
+         {:success? false
+          :message msg})))))

 (defmethod engine/columns-used "core/generate-geopoints"
   [applied-transformation columns]


routing.clj: Remove some blank lines.

routing.clj: Remove some blank lines.

--- src/statuses/routing.clj
+++ src/statuses/routing.clj
@@ -62,8 +62,6 @@
                             "text/html;charset=utf-8"
                             (list-page items next request)))))))

-
-
 (defn new-update [{:keys [form-params] :as request}]
   (let [{:strs [text reply-to]} form-params
         length (.length text)]


Get rid of concat usage

Get rid of concat usage

This will make the cljs port easier

--- src/superstring/core.clj
+++ src/superstring/core.clj
@@ -143,8 +143,8 @@
         full-lengths (Math/floor (/ missing (.length padding)))
         remaining (if (zero? full-lengths) (- width (.length s))
                       (rem missing (* full-lengths (.length padding))))]
-    (.concat (apply str (repeat full-lengths padding))
-             (.substring padding 0 remaining))))
+    (str (apply str (repeat full-lengths padding))
+         (.substring padding 0 remaining))))

 (defn ^String pad-right
@@ -158,7 +158,7 @@
     :post [(= (.length %) width)]}
    (if (<= width (.length s))
      s
-     (.concat s (gen-padding s padding width)))))
+     (str s (gen-padding s padding width)))))

 (defn ^String pad-left
   "Pad the beginning of s with padding, or spaces, until the length of
@@ -171,7 +171,7 @@
     :post [(= (.length %) width)]}
    (if (<= width (.length s))
      s
-     (.concat (gen-padding s padding width) s))))
+     (str (gen-padding s padding width) s))))

 (defn ^String center
   "Pad both ends of s with padding, or spaces, until the length of s


add indent

add indent

--- src/tamaki/post/post.clj
+++ src/tamaki/post/post.clj
@@ -27,14 +27,18 @@

 (def ^:private date-formatter (new SimpleDateFormat "yyyy-MM-dd"))

-(defn- compile-posts [site-root post-prefix dest post-dir compiler-map]
+(defn- compile-posts
+  [site-root post-prefix dest post-dir compiler-map]
   (letfn [(convert-filename
             [ml-filename]
             (string/replace ml-filename
                             #"(\d{4})-(\d{1,2})-(\d{1,2})-(.+)\.[^\.]+$"
                             "$1/$2/$3/$4/index.html"))
-          (build-suffix [post-prefix basename] (str post-prefix "/" (convert-filename basename)))
-          (extract-date [text-includes-date]
+          (build-suffix
+            [post-prefix basename]
+            (str post-prefix "/" (convert-filename basename)))
+          (extract-date
+            [text-includes-date]
             (let [maybe-date (first (re-seq #"\d{4}-\d?\d-\d?\d" text-includes-date))]
               (if (some? maybe-date) (.parse date-formatter maybe-date))))]


Added keyword parameters to draw-lattice

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

--- src/conexp/contrib/draw/lattices.clj
+++ src/conexp/contrib/draw/lattices.clj
@@ -15,7 +15,8 @@
                 with-printed-result,
                 now,
                 defvar-,
-                defmacro-)]
+                defmacro-,
+                defnk)]
 	[conexp.math.util
          :only (with-doubles)]
 	[conexp.layout
@@ -39,7 +40,8 @@
                 get-zoom-factors,
                 save-image,
                 get-canvas-from-scene,
-                show-labels)]
+                show-labels,
+                add-scrollbars)]
 	[conexp.contrib.draw.scene-layouts
          :only (draw-on-scene,
                 get-layout-from-scene,
@@ -364,7 +366,7 @@
 	(.add canvas BorderLayout/CENTER)
 	(.add hscrollbar BorderLayout/SOUTH)
 	(.add vscrollbar BorderLayout/EAST))
-      (.installScrollHandler scn hscrollbar vscrollbar)
+      (add-scrollbars scn hscrollbar vscrollbar)

       ;; main panel
       (doto main-panel
@@ -395,20 +397,26 @@

 ;;; Drawing Routine for the REPL

-(defn draw-lattice
-  "Draws given lattice with given layout-function on a canvas. Uses
-  *standard-layout-function* if no layout-function is given. Returns
-  the panel of the lattice editor."
-  ([lattice]
-     (draw-lattice lattice *standard-layout-function*))
-  ([lattice layout-function]
-     (let [^JFrame frame (JFrame. "conexp-clj Lattice"),
-           ^JPanel lattice-editor (make-lattice-editor frame (layout-function lattice))]
-       (doto frame
-	 (.add lattice-editor)
-	 (.setSize (Dimension. 600 600))
-	 (.setVisible true))
-       lattice-editor)))
+(defnk draw-lattice
+  "Draws given lattice with given layout-function on a canvas. Returns
+  the panel of the lattice editor. The following options are allowed,
+  their default values are given in paranthese:
+
+    - layout-fn (*standard-layout-function*)
+    - visible (true)
+    - dimension [600 600]
+  "
+  [lattice
+   :layout-fn *standard-layout-function*
+   :visible true
+   :dimension [600 600]]
+  (let [^JFrame frame (JFrame. "conexp-clj Lattice"),
+        ^JPanel lattice-editor (make-lattice-editor frame (layout-fn lattice))]
+    (doto frame
+      (.add lattice-editor)
+      (.setSize (Dimension. (first dimension) (second dimension)))
+      (.setVisible visible))
+    lattice-editor))

 ;;;


allow burst when interval <= exposure

allow burst when interval <= exposure

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

--- acqEngine/src/org/micromanager/sequence_generator.clj
+++ acqEngine/src/org/micromanager/sequence_generator.clj
@@ -117,7 +117,7 @@

 (defn burst-valid [e1 e2]
   (and
-    (#(or (nil? %) (zero? %)) (:wait-time-ms e2))
+    (#(or (nil? %) (>= (:exposure e2) %)) (:wait-time-ms e2))
     (select-values-match? e1 e2 [:exposure :position :slice :channel])
     (not (:autofocus e2))))


Removed old transducer code.

Removed old transducer code.

(Pasted these into a new file, but commented out.)

--- src/dragon/blog/core.clj
+++ src/dragon/blog/core.clj
@@ -4,6 +4,7 @@
             [dragon.blog.post.core :as post]
             [dragon.blog.post.impl.default :as default]
             [dragon.blog.tags :as tags]
+            [dragon.blog.workflow.core :as workflow]
             [dragon.components.core :as component-api]
             [dragon.config.core :as config]
             [dragon.data.sources.core :as data-source]
@@ -105,21 +106,6 @@
    :posts auth-data})

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;   Transducers   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defn ingest-transducer
-  ([system querier]
-    (ingest-transducer system querier default/new-processor))
-  ([system querier processor]
-    (comp
-      (post/process-one-file-data processor)
-      (filter (partial data-source/post-changed? querier))
-      (map (partial data-source/save-post querier))
-      (post/process-one-metadata processor)
-      (post/process-one-content processor))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;   Core Processing Functions   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

@@ -140,30 +126,13 @@
          ((fn [x] (log/debugf "Found %s files ..." (count x)) x))
          (map #(hash-map :file %)))))

-(defn ingest-posts
-  [system processor data]
-  (let [querier (component-api/get-db-querier system)]
-    (into [] (ingest-transducer system querier (processor)) data)))
-
-(defn- process-posts
-  [system]
-  (let [raw-posts (get-posts system)
-        processor-type (config/processor-type system)
-        processor (post/new-processor-fn system)]
-    (log/trace "Posts:" (vec raw-posts))
-    (log/debug "Processor type:" processor-type)
-    (log/debug "Processor constructor key:"
-               (config/processor-constructor system))
-    (log/debug "Processor constructor function:" processor)
-    (case processor-type
-      :transducer (ingest-posts system processor raw-posts)
-      :iterator (post/process-iter system processor raw-posts))))
-
 (defn process
   [system]
   (log/debug "Processing posts ...")
   (event/publish system tag/process-all-pre)
-  (let [processed-posts (process-posts system)]
+  (let [raw-posts (get-posts system)
+        wf (workflow/new-workflow system)
+        processed-posts (workflow/files->data wf raw-posts)]
   ;; XXX maybe doall here instead of using vec to realize?
   (->> processed-posts
        (sort compare-timestamp-desc)


[#408] create database can't run in a transaction

--- backend/src/org/akvo/lumen/admin/add_tenant.clj
+++ backend/src/org/akvo/lumen/admin/add_tenant.clj
@@ -8,7 +8,7 @@

 (defn migrate-tenant [db-uri]
   (ragtime.repl/migrate
-   {:datastore db-uri
+   {:datastore (ragtime.jdbc/sql-database db-uri)
     :migrations (ragtime.jdbc/load-resources "org/akvo/lumen/migrations/tenants")}))

 (defn -main [label title]
@@ -20,10 +20,13 @@
         tenant-password (s/replace (squuid) "-" "")
         db-uri (format "jdbc:postgresql://%s/%s?user=%s&password=%s"
                        pg-host pg-database pg-user pg-password)
+        lumen-db-uri (format "jdbc:postgresql://%s/lumen?user=lumen&password=%s"
+                             pg-host pg-password)
         tenant-db-uri (format "jdbc:postgresql://%1$s/%2$s?user=%2$s&password=%3$s"
                               pg-host tenant tenant-password)
         exec! (fn [format-str & args]
-                (jdbc/execute! db-uri [(apply format format-str args)]))]
+                (jdbc/execute! db-uri [(apply format format-str args)]
+                               {:transaction? false}))]
     (exec! "CREATE ROLE %s WITH PASSWORD '%s' LOGIN;" tenant tenant-password)
     (exec! (str "CREATE DATABASE %1$s "
                 "WITH OWNER = %1$s "
@@ -34,5 +37,5 @@
            tenant)
     (exec! "CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA public;")
     (exec! "CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public;")
-    (jdbc/insert! db-uri :tenants {:db_uri tenant-db-uri :label label :title title})
+    (jdbc/insert! lumen-db-uri :tenants {:db_uri tenant-db-uri :label label :title title})
     (migrate-tenant tenant-db-uri)))


port 2323

port 2323

so we don't need sudo

--- clojure/src/dnd/core.cljs
+++ clojure/src/dnd/core.cljs
@@ -113,7 +113,7 @@
       (def term (.createTerminal tkit
                                  #js {:stdin client :stdout client}))
       (kick-it term)))
-   (.listen 23)))
+   (.listen 2323)))

 (defn -main []
   (prn "main")


Add Language Specific Links

Add Language Specific Links

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -345,18 +345,22 @@
                                    (sort-by first))))
               [:div.loading-spinner common/spinner]))])))))

-(defn tests-ad [owner]
-  [:div
-   "With some of our inferred build commands we collect test metadata automatically, but that didn't happen for this project.  Collecting metadata allows us to list the specific failures, and in some cases makes parallel builds more efficient.  Here's how to get it:"
-   [:ul
-    [:li "For an inferred ruby test command, simply add the necessary "
-     [:a {:href "/docs/test-metadata#automatic-test-metadata-collection"} "formatter gem"]]
-    [:li "Python should work automatically, except for django you'll need to " [:a {:href "/docs/test-metadata#automatic-test-metadata-collection"} "use django-nose"] "."]
-    [:li "For another inferred test runner that you'd like us to add metadata support for, "
-     [:a (common/contact-support-a-info owner)
-      "let us know"] "."]
-    [:li "For a custom test command, configure your test runner to write a JUnit XML report to a directory in $CIRCLE_TEST_REPORTS - see "
-     [:a {:href "/docs/test-metadata#metadata-collection-in-custom-test-steps"} "the docs"] " for more information."]]])
+(defn tests-ad [owner language]
+      [:div
+       "Help us provide better insight around your tests and failures. "
+       [:a {:href (case language
+           "Clojure" "/docs/test-metadata#test2junit-for-clojure-tests"
+           "Ruby" "/docs/test-metadata#rspec"
+           "JavaScript" "/docs/test-metadata#js"
+           "Python" "/docs/test-metadata#python"
+           "Java" "/docs/test-metadata#java-junit-results-with-maven-surefire-plugin"
+           "/docs/test-metadata#metadata-collection-in-custom-test-steps")}
+        "Set up your test runner to output in JUnit-style XML"] ", so we can:"
+       [:ul
+        [:li "Show a summary of all test failures across all containers"]
+        [:li "Identify the slowest test"]
+        [:li "Balance tests between containers when using properly configured parallelization"]]
+       ])

 (defmulti format-test-name test-model/source)

@@ -441,9 +445,10 @@
                  (when (om/get-state owner :is-open?)
                    (om/build-all build-tests-file-block bottom-map))))))]]]]))))

-(defn build-tests-list [{{tests :tests} :tests-data
+(defn build-tests-list [{project :project
+                        {{tests :tests} :tests-data
                          {build-status :status} :build
-                         :as data}
+                         :as data} :build-data}
                         owner]
   (reify
     om/IWillMount
@@ -491,7 +496,7 @@
               :else [:div.alert.iconified {:class (if build-succeeded? "alert-info" "alert-danger")}
                      [:div [:img.alert-icon {:src (common/icon-path
                                                    (if build-succeeded? "Info-Info" "Info-Error"))}]]
-                     (tests-ad owner)]))])))))
+                     (tests-ad owner (:language project))]))])))))

 (defn circle-yml-ad []
   [:div
@@ -742,7 +747,8 @@
           [:div.card.sub-head-content {:class (str "sub-head-" (name selected-tab))}
            (case selected-tab

-             :tests (om/build build-tests-list build-data)
+             :tests (om/build build-tests-list {:build-data build-data
+                                                :project project})

              :build-timing (om/build build-timings/build-timings {:build build
                                                                   :project project


Updated docstrings in the process-info module

--- src/emender_jenkins/process_info.clj
+++ src/emender_jenkins/process_info.clj
@@ -14,6 +14,7 @@
     "Functions that retrieve basic information about the service process.")

 (defn get-current-pid
+    "Returns process ID for current process."
     []
     (-> (java.lang.management.ManagementFactory/getRuntimeMXBean)
         (.getName)
@@ -21,6 +22,7 @@
         (first)))

 (defn read-properties
+    "Read all properties of the operation system and JVM."
     []
     {:java-version    (System/getProperty "java.version")
      :java-class-path (System/getProperty "java.class.path")


PLD: remove unneeded multimethod

PLD: remove unneeded multimethod

--- src/hatti/ona/forms.cljs
+++ src/hatti/ona/forms.cljs
@@ -147,13 +147,12 @@
 (defn get-label
   "Gets the label object out of a map with key :label (eg. a field).
    If multiple languages, and none specified, picks out alphabetically first."
-  ([labelled-obj] (get-label labelled-obj nil))
-  ([{:keys [label name]} & [language]]
-   (if-not (map? label)
-     (or label name)
-     (if (contains? (-> label keys set) language)
-       (label language)
-       (label (-> label keys sort first))))))
+  [{:keys [label name]} & [language]]
+  (if-not (map? label)
+    (or label name)
+    (if (contains? (-> label keys set) language)
+      (label language)
+      (label (-> label keys sort first)))))

 (defn format-answer
   "String representation for a particular field datapoint (answer).


figwheel.main: use load end to handle the build option

--- figwheel-main/src/figwheel/main.cljc
+++ figwheel-main/src/figwheel/main.cljc
@@ -277,16 +277,20 @@
 (defn figwheel-opt [cfg bl]
   (assoc-in cfg [::config :figwheel-core] (not= bl "false")))

+
+
 (defn get-build [bn]
-  (let [fname (str bn ".cljs.edn")
-        build (if-not (.isFile (io/file fname))
-                (throw (ex-info (str "Unable to find build file: " fname)
-                                {:filename fname}))
-                (read-edn-file fname))]
+  (let [fname (if (.contains bn (System/getProperty "path.separator"))
+                bn
+                (str bn ".cljs.edn"))
+        build (->> (cljs.util/split-paths bn)
+                   (map #(str % ".cljs.edn"))
+                   (string/join (System/getProperty "path.separator"))
+                   load-edn-opts)]
     (when (meta build)
       (when-not (false? (:validate-config (meta build)))
-        (log/debug "Validating metadata in build: " fname)
-        (validate-config! (meta build) (str "Configuration error in " fname))))
+        (log/debug "Validating metadata in build option: " fname)
+        (validate-config! (meta build) (str "Configuration error in build options meta data:" fname))))
     build))

 (defn watch-dir-from-ns [main-ns]


Remove fs-diff! function

Remove fs-diff! function

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -79,12 +79,6 @@
   [fileset]
   (->> fileset core/input-files (core/by-ext [".cljs" ".cljc"]) (sort-by :path)))

-(defn- fs-diff!
-  [state fileset]
-  (let [s @state]
-    (reset! state fileset)
-    (core/fileset-diff s fileset)))
-
 (defn- macro-files-changed
   [diff]
   (->> (core/input-files diff)
@@ -213,7 +207,7 @@
         ;; task in the pipeline we need to remove them from the classpath
         ;; or the cljs compiler will try to use them during compilation.
         (-> fileset remove-previous-cljs-output core/commit!)
-        (let [diff          (fs-diff! prev fileset)
+        (let [diff          (core/fileset-diff @prev fileset)
               macro-changes (macro-files-changed diff)
               cljs-edns (main-files fileset ids)
               ;; Force realization to start compilation
@@ -228,6 +222,7 @@
               ;; builds. Each :output-to js file will depend only on compiled
               ;; namespaces in its own :output-dir, including goog/base.js etc.
               dep-order (reduce into [] (map :dep-order results))]
+          (reset! prev fileset)
           (->> (vals @compilers)
                (map #(get-in % [:initial-ctx :tmp-out]))
                (apply core/sync! tmp-result))


remove default route

remove default route

--- resources/leiningen/new/glimpse_app/routes.clj
+++ resources/leiningen/new/glimpse_app/routes.clj
@@ -3,5 +3,6 @@
               [glimpse.views :as glimpse]))

 (defroutes {{name}}-routes
-  (GET "/" request (-> (glimpse/view (:uri request))
-                       (glimpse/render))))
+  ;; Here is where you add your application routes, e.g.:
+  ;; (GET "/" [] (glimpse/render (glimpse/view "/")))
+)


generic navigation-data

generic navigation-data

--- frontend/controllers/navigation.cljs
+++ frontend/controllers/navigation.cljs
@@ -47,13 +47,13 @@
   [history-imp to args state]
   (-> state
       (assoc :navigation-point :dashboard
-             :dashboard-data (select-keys args [:branch :repo :org]))
+             :navigation-data (select-keys args [:branch :repo :org]))
       state-utils/reset-current-build))

 (defmethod post-navigated-to! :dashboard
   [history-imp to args previous-state current-state]
   (let [api-ch (get-in current-state [:comms :api])
-        dashboard-data (:dashboard-data current-state)]
+        dashboard-data (:navigation-data current-state)]
     (api/get-projects api-ch)
     (api/get-dashboard-builds dashboard-data api-ch))
   (set-page-title!))
@@ -62,8 +62,8 @@
 (defmethod navigated-to :build-inspector
   [history-imp to [project-name build-num] state]
   (-> state
-      (assoc :inspected-project {:project project-name
-                                 :build-num build-num}
+      (assoc :navigation-data {:project project-name
+                               :build-num build-num}
              :navigation-point :build
              :project-settings-project-name project-name)
       state-utils/reset-current-build
@@ -101,7 +101,7 @@

 (defmethod navigated-to :add-projects
   [history-imp to [project-id build-num] state]
-  (assoc state :navigation-point :add-projects))
+  (assoc state :navigation-point :add-projects :navigation-data {}))

 (defmethod post-navigated-to! :add-projects
   [history-imp to args previous-state current-state]
@@ -115,6 +115,7 @@
   [history-imp to {:keys [project-name subpage]} state]
   (-> state
       (assoc :navigation-point :project-settings)
+      (assoc :navigation-data {}) ;; XXX: maybe put subpage info here?
       (assoc :project-settings-subpage subpage)
       (assoc :project-settings-project-name project-name)
       (#(if (state-utils/stale-current-project? % project-name)


add __typename to :interface-definition

add __typename to :interface-definition

--- src/graphql_clj/schema_validator.clj
+++ src/graphql_clj/schema_validator.clj
@@ -135,10 +135,12 @@
 (def default-field-map {'__typename default-typename-field})

 (defmethod build-member-map :typedef [errors tdef]
-  (let [init-fields (if (= :type-definition (:tag tdef))
+  (let [init-fields (if (or (= :type-definition (:tag tdef))
+                            (= :interface-definition (:tag tdef)))
                       default-fields
                       [])
-        init-field-map (if (= :type-definition (:tag tdef))
+        init-field-map (if (or (= :type-definition (:tag tdef))
+                               (= :interface-definition (:tag tdef)))
                          default-field-map
                          {})]
     (loop [errors errors fields init-fields field-map init-field-map [f & fs :as fseq] (seq (:fields tdef))]


Remove old tests

Remove old tests

--- test/aurora/btree_test.cljs
+++ test/aurora/btree_test.cljs
@@ -1,11 +1,9 @@
 (ns aurora.btree-test
   (:require [aurora.btree :refer [tree]]
-            [aurora.join :refer [magic-iterator join-iterator all-join-results constant-filter]]
             [cemerick.cljs.test :refer [run-all-tests]])
   (:require-macros [aurora.macros :refer [apush apush* lt lte gt gte set!! dofrom]]
                    [cemerick.cljs.test :refer [deftest is]]
                    [cemerick.double-check.clojure-test :refer [defspec]]))
-

 (defspec least-prop-test
   1000
@@ -98,319 +96,3 @@
 (defspec product-join-prop-test
   5000
   (aurora.btree/product-join-prop 3))
-
-;;; MAGIC!
-
-(defspec magic-self-join-prop-test-1
-  3000
-  (aurora.join/magic-self-join-prop 1))
-
-(defspec magic-self-join-prop-test-2
-  3000
-  (aurora.join/magic-self-join-prop 2))
-
-(defspec magic-self-join-prop-test-3
-  3000
-  (aurora.join/magic-self-join-prop 3))
-
-(defspec magic-product-join-prop-test-1
-  3000
-  (aurora.join/magic-product-join-prop 1))
-
-(defspec magic-product-join-prop-test-2
-  3000
-  (aurora.join/magic-product-join-prop 2))
-
-(defspec magic-product-join-prop-test-3
-  3000
-  (aurora.join/magic-product-join-prop 3))
-
-(deftest join-3-2
-  (println "testing: join-3-2")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [0 1 4]
-                     #js [0 1 6]
-                     #js [1 1 7]
-                     #js [1 2 7]
-                     #js [1 3 3]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [0 3]
-                     #js [0 6]
-                     #js [1 3]
-                     #js [1 7]]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0 1 2])
-        itr2 (magic-iterator tree2 #js [0 nil 1])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [0 1 6] #js [1 1 7] #js [1 2 7] #js [1 3 3] ])))
-    ))
-
-(deftest join-3-2-again
-  (println "testing: join-3-2-again")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1 0 1]
-                     #js [1 2 3]
-                     #js [1 3 1]
-                     #js [1 4 4]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [1 1]
-                     #js [1 3]
-                     #js [1 4]]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0 1 2])
-        itr2 (magic-iterator tree2 #js [0 nil 1])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [1 0 1] #js [1 2 3] #js [1 3 1] #js [1 4 4]])))
-    ))
-
-(deftest join-3-2-again2
-  (println "testing: join-3-2-again2")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1 0 1]
-                     #js [1 2 3]
-                     #js [1 3 1]
-                     #js [1 4 4]
-                     #js [2 2 3]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [2 3]
-                     #js [4 4]]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0 1 2])
-        itr2 (magic-iterator tree2 #js [nil 0 1])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [1 2 3] #js [1 4 4] #js [2 2 3] ])))
-    ))
-
-(deftest join-3-2-2
-  (println "testing: join-3-2-2")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1 0 1]
-                     #js [1 2 3]
-                     #js [1 3 1]
-                     #js [1 4 4]
-                     #js [2 2 3]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [2 3]
-                     #js [4 4]]]
-            (.assoc! tree2 x 0))
-        tree3 (tree 10)
-        _ (doseq [x [#js [1 1]
-                     #js [1 3]
-                     #js [1 4]]]
-            (.assoc! tree3 x 0))
-        itr1 (magic-iterator tree1 #js [0 1 2])
-        itr2 (magic-iterator tree2 #js [nil 0 1])
-        itr3 (magic-iterator tree3 #js [0 nil 1])
-        join-itr (join-iterator #js [itr1 itr2 itr3])
-        ]
-
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [1 2 3] #js [1 4 4] ])))
-    ))
-
-(deftest join-product
-  (println "testing: join-product")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js ["3"]
-                     #js [-3]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js ["3"]
-                     #js [-3]
-                     ]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0 nil])
-        itr2 (magic-iterator tree2 #js [nil 0])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [-3 -3] #js [-3 "3"]  #js ["3" -3] #js ["3" "3"] ])))
-    ))
-
-(deftest self-join
-  (println "testing: self-join")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1]
-                     #js [4]
-                     #js [2]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [3]
-                     #js [6]
-                     #js [4]
-                     ]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0])
-        itr2 (magic-iterator tree2 #js [0])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [4] ])))
-    ))
-
-(deftest join-product-2
-  (println "testing: join-product-2")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1]
-                     #js [4]
-                     #js [2]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [3]
-                     #js [6]
-                     #js [4]
-                     ]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0 nil])
-        itr2 (magic-iterator tree2 #js [nil 0])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [1 3] #js [1 4] #js [1 6] #js [2 3] #js [2 4] #js [2 6] #js [4 3] #js [4 4] #js [4 6] ])))
-    ))
-
-(deftest join-4-2-offest
-  (println "testing: join-4-2-offset")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1 2 1 3]
-                     #js [1 2 2 5]
-                     #js [1 2 3 3]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [2 3]
-                     #js [2 6]
-                     #js [4 4]
-                     ]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0 1 2 3])
-        itr2 (magic-iterator tree2 #js [nil 0 nil 1])
-        join-itr (join-iterator #js [itr1 itr2])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [1 2 1 3] #js [1 2 3 3] ])))
-    ))
-
-(deftest join-join
-  (println "testing: join-join")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1]
-                     #js [4]
-                     #js [2]
-                     #js [7]
-                     #js [9]
-                     ]]
-            (.assoc! tree1 x 0))
-        tree2 (tree 10)
-        _ (doseq [x [#js [3]
-                     #js [6]
-                     #js [4]
-                     #js [8]
-                     #js [9]
-                     ]]
-            (.assoc! tree2 x 0))
-        itr1 (magic-iterator tree1 #js [0])
-        itr2 (magic-iterator tree2 #js [0])
-        itr3 (magic-iterator tree1 #js [0])
-        join-itr (join-iterator #js [itr1 itr2])
-        join-itr2 (join-iterator #js [join-itr itr3])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr2))
-        (map vec #js [#js [4] #js [9] ])))
-    ))
-
-(deftest one-itr-join
-  (println "testing: one-itr-join")
-  (let [tree1 (tree 10)
-        _ (doseq [x [#js [1 "get books" "active"]
-                     #js [2 "buy milk" "active"]
-                     #js [3 "learn spanish" "completed"]
-                     ]]
-            (.assoc! tree1 x 0))
-        itr1 (magic-iterator tree1 #js [0 1 2])
-        join-itr (join-iterator #js [itr1])
-        ]
-    (is
-     (= (map vec (all-join-results join-itr))
-        (map vec #js [#js [1 "get books" "active"] #js [2 "buy milk" "active"] #js [3 "learn spanish" "completed"]])))
-
-    ))
-
-  (deftest simple-filter
-    (println "testing: simple-filter")
-    (let [tree1 (tree 10)
-          _ (doseq [x [#js [1 "get books" "active"]
-                       #js [2 "buy milk" "active"]
-                       #js [3 "learn spanish" "completed"]
-                       ]]
-              (.assoc! tree1 x 0))
-          itr1 (magic-iterator tree1 #js [0 1 2])
-          filter (constant-filter 3 2 "completed")
-          join-itr (join-iterator #js [itr1 filter])
-          ]
-      (is
-       (= (map vec (all-join-results join-itr))
-          (map vec #js [#js [3 "learn spanish" "completed"]])))
-
-      ))
-
-
-  (deftest todomvc-filter
-    (println "testing: todomvc-filter")
-    (let [tree1 (tree 10)
-          _ (doseq [x [#js [1 "get books" "active"]
-                       #js [2 "buy milk" "active"]
-                       #js [3 "learn spanish" "completed"]
-                       #js [4 "learn something" "active"]
-                       ]]
-              (.assoc! tree1 x 0))
-          tree2 (tree 10)
-          _ (doseq [x [#js [1 "editing"]
-                       #js [2 "editing"]
-                       #js [3 "editing"]
-                       #js [4 "editing"]
-                       ]]
-              (.assoc! tree2 x 0))
-          itr1 (magic-iterator tree1 #js [0 1 2 nil])
-          itr2 (magic-iterator tree2 #js [0 nil nil 1])
-          filter (constant-filter 4 2 "active")
-          join-itr (join-iterator #js [itr1 itr2 filter])
-          ]
-      (is
-       (= (map vec (all-join-results join-itr))
-          (map vec #js [#js [1 "get books" "active" "editing"] #js [2 "buy milk" "active" "editing"] #js [4 "learn something" "active" "editing"]])))
-
-      ))
-
-
-(comment
-  (run-all-tests)
-
-  )


Tear down resources when stopping communicator resources

According to comments from Peter Taoussanis: https://github.com/ptaoussanis/sente/issues/72#issuecomment-55554663

--- Clojure-Websockets/src/clj/birdwatch/communicator.clj
+++ Clojure-Websockets/src/clj/birdwatch/communicator.clj
@@ -64,7 +64,7 @@
              (chsk-send! (:uid res) [:tweet/prev-chunk (:result res)]))
            (recur)))

-(defrecord Communicator [channels]
+(defrecord Communicator [channels chsk-router]
   component/Lifecycle
   (start [component]
          (log/info "Starting Communicator Component")
@@ -77,8 +77,12 @@
            (run-tweet-stats-loop send-fn connected-uids (:tweet-count channels))
            (run-missing-tweet-loop (:missing-tweet-found channels) send-fn)
            (run-query-results-loop (:query-results channels) send-fn)
-           (assoc component :ajax-post-fn ajax-post-fn :ajax-get-or-ws-handshake-fn ajax-get-or-ws-handshake-fn)))
+           (assoc component :ajax-post-fn ajax-post-fn
+                            :ajax-get-or-ws-handshake-fn ajax-get-or-ws-handshake-fn
+                            :chsk-router chsk-router)))
   (stop [component]
-        (log/info "Stopping Persistence Component"))) ;; TODO: teardown
+        (log/info "Stopping Communicator Component")
+        (chsk-router) ;; stops router loop
+        (assoc component :chsk-router nil)))

 (defn new-communicator [] (map->Communicator {}))


show overlay text in the foreground

show overlay text in the foreground

--- src/zombie_run/view.cljs
+++ src/zombie_run/view.cljs
@@ -88,13 +88,12 @@
    (into
      [:svg.world
       {:view-box "0 0 100 100"}]
-     (mapcat identity
-             [[(display-health-text game-state)
+     (concat (display-player game-state)

-               (make-fire-tip-text)
+             (display-zombies game-state)

-               (display-overlay-text game-state)]
+             [(display-health-text game-state)

-              (display-player game-state)
+              (make-fire-tip-text)

-              (display-zombies game-state)]))])
+              (display-overlay-text game-state)]))])


Version 0.1.3-SNAPSHOT

Version 0.1.3-SNAPSHOT

--- metlog-agent/project.clj
+++ metlog-agent/project.clj
@@ -1,4 +1,4 @@
-(defproject metlog-agent "0.1.2"
+(defproject metlog-agent "0.1.3-SNAPSHOT"
   :description "Metlog agent - polls data sources for upload to vault."

   :license {:name "Eclipse Public License"


consistent wizard layout across steps

consistent wizard layout across steps

--- priv/ui/src/cljs/holiday_ping_ui/channels/views.cljs
+++ priv/ui/src/cljs/holiday_ping_ui/channels/views.cljs
@@ -150,8 +150,6 @@
         on-prev      (get prev :event prev)
         on-next      (get next :event next)]
     [:div
-     [:br]
-     [:br]
      [:nav.level
       [:div.level-left
        (when show-prev?
@@ -170,6 +168,10 @@
            [:span.icon.is-small
             [:i.fa.fa-chevron-right]]]]])]]))

+(defn step-title
+  [text]
+  [:p.subtitle.is-5.has-text-centered text])
+
 (defn select-type-event
   [state type]
   #(do (swap! state update :step-n inc)
@@ -178,7 +180,7 @@
 (defn type-select
   [wizard-state]
   [:div
-   [:p.subtitle.is-6 "Select the type of the channel you want to use."]
+   [step-title "Select the type of the channel you want to use."]
    [:p
     [:a {:href "#" :on-click (select-type-event wizard-state :slack)}
      "Slack"]]
@@ -193,132 +195,131 @@
   [wizard-state]
   (let [channel-state (reagent/cursor wizard-state [:channel-config])
         valid-form?   @(re-frame/subscribe [:valid-slack-config? @channel-state])]
-    [:div
-     [:br]
-     [:p.subtitle.is-6 "Fill the configuration for the slack integration."]
-     [forms/detached-form-view channel-state
-      ;; TODO add a name already taken validation
-      {:fields [{:key      :name
-                 :type     "text"
-                 :required true}
-                {:key       :url
-                 :type      "text"
-                 :label     "Slack hook url"
-                 :validate  :valid-slack-hook?
-                 :help-text [:span "You can get the hook url "
-                             [:a {:href   "https://my.slack.com/services/new/incoming-webhook/"
-                                  :target "blank"} "here."]]
-                 :required  true}
-                {:key       :targets
-                 :type      "text"
-                 :label     "Targets"
-                 :validate  :valid-slack-targets?
-                 :help-text "Where to send the message. Space separated, use \"#name\" for channels and \"@name\" for users. If left empty, the channel configured in the Slack hook will be used."}
-                {:key       :username
-                 :type      "text"
-                 :label     "Bot username"
-                 :help-text "Defaults to :calendar:"}
-                {:key       :emoji
-                 :type      "text"
-                 :label     "Bot emoji"
-                 :help-text "Defaults to HolidayPing"}]}]
-     [wizard-navigation (dec-step wizard-state) {:static (not valid-form?)
-                                                 :event  (inc-step wizard-state)}]]))
+    [:div.columns.is-centered
+     [:div.column.is-half
+      [step-title "Fill the configuration for the slack integration."]
+      [forms/detached-form-view channel-state
+       ;; TODO add a name already taken validation
+       {:fields [{:key      :name
+                  :type     "text"
+                  :required true}
+                 {:key       :url
+                  :type      "text"
+                  :label     "Slack hook url"
+                  :validate  :valid-slack-hook?
+                  :help-text [:span "You can get the hook url "
+                              [:a {:href   "https://my.slack.com/services/new/incoming-webhook/"
+                                   :target "blank"} "here."]]
+                  :required  true}
+                 {:key       :targets
+                  :type      "text"
+                  :label     "Targets"
+                  :validate  :valid-slack-targets?
+                  :help-text "Where to send the message. Space separated, use \"#name\" for channels and \"@name\" for users. If left empty, the channel configured in the Slack hook will be used."}
+                 {:key       :username
+                  :type      "text"
+                  :label     "Bot username"
+                  :help-text "Defaults to :calendar:"}
+                 {:key       :emoji
+                  :type      "text"
+                  :label     "Bot emoji"
+                  :help-text "Defaults to HolidayPing"}]}]
+      [wizard-navigation (dec-step wizard-state) {:static (not valid-form?)
+                                                  :event  (inc-step wizard-state)}]]]))

 (defn webhook-config-form
   [wizard-state]
   [:div
    [:br]
-   [:p.subtitle.is-6 "Fill the configuration for the webhook integration."]
+   [step-title "Fill the configuration for the webhook integration."]
    ])

 (defn email-config-form
   [wizard-state]
   [:div
    [:br]
-   [:p.subtitle.is-6 "Fill the configuration for the email integration."]
+   [step-title "Fill the configuration for the email integration."]
    ])

 (defn reminder-config-form
   [wizard-state]
   (let [reminder-state (reagent/cursor wizard-state [:reminder-config])]
-    [:div
-     [:br]
-     [:p.subtitle.is-6 "When you want the reminders sent?"]
-     [forms/detached-form-view reminder-state
-      {:fields [{:key     :same-day
-                 :label   "Send a reminder on the same day."
-                 :type    "select"
-                 :options [{:text "Yes" :value true}
-                           {:text "Don't send" :value false}]}
-                {:key     :days-before
-                 :label   "Send a reminder before the holiday."
-                 :type    "select"
-                 :options [{:text "Don't send" :value 0}
-                           {:text "The day before" :value 1}
-                           {:text "Three days before" :value 3}
-                           {:text "A week before" :value 7}]}]}]
-     [wizard-navigation (dec-step wizard-state) (inc-step wizard-state)]]))
+    [:div.columns.is-centered
+     [:div.column.is-half
+      [step-title "When you want the reminders sent?"]
+      [forms/detached-form-view reminder-state
+       {:fields [{:key     :same-day
+                  :label   "Send a reminder on the same day."
+                  :type    "select"
+                  :options [{:text "Yes" :value true}
+                            {:text "Don't send" :value false}]}
+                 {:key     :days-before
+                  :label   "Send a reminder before the holiday."
+                  :type    "select"
+                  :options [{:text "Don't send" :value 0}
+                            {:text "The day before" :value 1}
+                            {:text "Three days before" :value 3}
+                            {:text "A week before" :value 7}]}]}]
+      [wizard-navigation (dec-step wizard-state) (inc-step wizard-state)]]]))

 (defn holiday-source-form
   [wizard-state]
   (let [source-state (reagent/cursor wizard-state [:source-config])
         channels     @(re-frame/subscribe [:channels])
         source       (:source @source-state)]
-    [:div
-     [:br]
-     [:p.subtitle.is-6 "What holidays do you want by default on your calendar?"]
-
-     [:form
-      [:div.field
-       [:div.control
-        [:label.radio
-         [:input {:type      "radio"
-                  :name      "from-country"
-                  :checked   (= source :country)
-                  :on-change #(swap! source-state assoc :source :country)}]
-         " Use country defaults"]]]
-      [:div.field
-       [:div.control
-        [forms/input-view source-state
-         {:key      :country
-          :type     "select"
-          :disabled (not= source :country)
-          :options  ["Argentina" "Brazil" "United States"]}]]]
-      [:br]
-
-      (when-not (empty? channels)
-        [:div
-         [:div.field
-          [:div.control
-           [:label.radio
-            [:input {:type      "radio"
-                     :name      "from-channel"
-                     :checked   (= source :channel)
-                     :on-change #(swap! source-state assoc :source :channel)}]
-            " Copy from another channel"]]]
-         [:div.field
-          [:div.control
-           [forms/input-view source-state
-            {:key      :channel
-             :type     "select"
-             :disabled (not= source :channel)
-             :options  (map :name channels)}]]]
-         [:br]])
-
-      [:div.field
-       [:div.control
-        [:label.radio
-         [:input {:type      "radio"
-                  :name      "empty"
-                  :checked   (= source :empty)
-                  :on-change #(swap! source-state assoc :source :empty)}]
-         " Start with an empty calendar"]]]]
-
-     [wizard-navigation
-      (dec-step wizard-state)
-      #(do (re-frame/dispatch [:load-base-holidays @source-state])
-           (swap! wizard-state update :step-n inc))]]))
+    [:div.columns.is-centered
+     [:div.column.is-half
+      [step-title "What holidays do you want by default on your calendar?"]
+      [:form
+       [:div.field
+        [:div.control
+         [:label.radio
+          [:input {:type      "radio"
+                   :name      "from-country"
+                   :checked   (= source :country)
+                   :on-change #(swap! source-state assoc :source :country)}]
+          " Use country defaults"]]]
+       [:div.field
+        [:div.control
+         [forms/input-view source-state
+          {:key      :country
+           :type     "select"
+           :disabled (not= source :country)
+           :options  ["Argentina" "Brazil" "United States"]}]]]
+       [:br]
+
+       (when-not (empty? channels)
+         [:div
+          [:div.field
+           [:div.control
+            [:label.radio
+             [:input {:type      "radio"
+                      :name      "from-channel"
+                      :checked   (= source :channel)
+                      :on-change #(swap! source-state assoc :source :channel)}]
+             " Copy from another channel"]]]
+          [:div.field
+           [:div.control
+            [forms/input-view source-state
+             {:key      :channel
+              :type     "select"
+              :disabled (not= source :channel)
+              :options  (map :name channels)}]]]
+          [:br]])
+
+       [:div.field
+        [:div.control
+         [:label.radio
+          [:input {:type      "radio"
+                   :name      "empty"
+                   :checked   (= source :empty)
+                   :on-change #(swap! source-state assoc :source :empty)}]
+          " Start with an empty calendar"]]]]
+
+      [wizard-navigation
+       (dec-step wizard-state)
+       #(do (re-frame/dispatch [:load-base-holidays @source-state])
+            (swap! wizard-state update :step-n inc))]]]))

 (defn holiday-controls
   [wizard-state]
@@ -349,7 +350,7 @@
         selected-year @(re-frame/subscribe [:calendar-selected-year])]
     [:div
      [holidays/edit-holiday-modal]
-     [:p.subtitle.is-6 "Select the days of the year for which you want reminders."]
+     [step-title "Select the days of the year for which you want reminders."]
      [holiday-controls wizard-state]
      [:div (when-not (= selected-year current-year) {:hidden true})
       [calendar/year-view current-year]]
@@ -360,9 +361,9 @@

 (defn wizard-steps
   "Show the wizard steps and navigate on click."
-  [wizard-state step-n size]
+  [wizard-state step-n]
   [:div.columns.is-centered
-   [:div.column {:class (name size)}
+   [:div.column.is-half
     [:div.steps.is-small
      (for [[i title] [[0 "Channel type"]
                       [1 "Channel config"]
@@ -388,26 +389,31 @@
           [:div.step-marker]
           [:div.step-content [:p.step-title title]]]))]]])

+(def initial-wizard-state
+  {:step-n          0
+   :type            :slack
+   :channel-config  {}
+   :reminder-config {:same-day    true
+                     :days-before 0}
+   :source-config   {:source  :country
+                     :country "Argentina"}})
+
+(def step-keys [:type-select
+                :channel-config
+                :reminder-config
+                :holidays-source
+                :holidays])
+
 (defn create-view
   []
-  (let [wizard-state (reagent/atom {:step-n          0
-                                    :type            :slack
-                                    :channel-config  {}
-                                    :reminder-config {:same-day    true
-                                                      :days-before 0}
-                                    :source-config   {:source  :country
-                                                      :country "Argentina"}})]
+  (let [wizard-state (reagent/atom initial-wizard-state)]
     (fn []
-      (let [step-keys    [:type-select :channel-config :reminder-config :holidays-source :holidays]
-            step-n       (:step-n @wizard-state)
-            step         (get step-keys step-n)
-            wide?        (contains? #{:type-select :holidays} step)
-            section-size (if wide? :is-full :is-half)
-            wizard-size  (if wide? :is-half :is-full)]
+      (let [step-n (:step-n @wizard-state)
+            step   (get step-keys step-n)]
         [:div
-         [views/section-size section-size
+         [views/section
           [views/breadcrumbs [["Channels" "/"] ["New"]]]
-          [wizard-steps wizard-state step-n wizard-size]
+          [wizard-steps wizard-state step-n]
           (case step
             :type-select     [type-select wizard-state]
             :channel-config  (case (:type @wizard-state)


Check that variables are strings

Check that variables are strings

--- src/aurora/language.cljs
+++ src/aurora/language.cljs
@@ -216,6 +216,10 @@
                       (aset fields (var->ix val) key))
                     (Sink. clause-type name fields)))]

+    (doseq [[clause-id field-type key val] fields
+            :when (= "variable" field-type)]
+      (assert (string? val) [clause-id key val]))
+
     ;; rewrite clauses
     (doseq [[rule-id clauses] @rule-id->clauses]
       (doseq [[_ clause-type clause-id name] clauses


#12 order posts by date desc

#12 order posts by date desc

--- src/kalar_plugins/templates/page.clj
+++ src/kalar_plugins/templates/page.clj
@@ -9,10 +9,6 @@
             [kalar-core.file :as kfile])
   (:import (java.io StringWriter StringReader)
            (java.text SimpleDateFormat)))
-
-(defn- get-dst-path [^String src-path]
-  (kfile/get-dst (str/replace src-path #"\..*$" ".html")))
-

 (def ^:private date-formatter (SimpleDateFormat. "yyyy-MM-dd"))

@@ -80,7 +76,7 @@
             (cons "index.html"
                   (map #(str/replace paginate-url-pattern #":num" (str %)) (range 2 (+ 1 total)))))]
     (let [paginate (:paginate (config/read-config))
-          mds (map #(load-md-excerpt (.getAbsolutePath %)) (.listFiles (io/file dir)))
+          mds (map #(load-md-excerpt (.getAbsolutePath %)) (-> dir io/file .listFiles reverse))
           mdchunks (partition-all paginate mds)
           paginate (create-paginate (count mdchunks) (:paginate-path (config/read-config)))
           paginate2 (create-neighbor-url paginate)


Minor refactoring of tracker

Minor refactoring of tracker

--- src/main/clojure/clojure/tools/namespace/tracker.clj
+++ src/main/clojure/clojure/tools/namespace/tracker.clj
@@ -3,25 +3,25 @@
             [clojure.tools.namespace :as tns]
             [clojure.tools.namespace.dependency :as dep]))

-(defn- remove-deps [deps new-decls]
-  (reduce dep/remove-key deps (map second new-decls)))
+(defn- remove-deps [deps decls]
+  (reduce dep/remove-key deps (map second decls)))

-(defn- add-deps [deps new-decls]
+(defn- add-deps [deps decls]
   (reduce (fn [ds decl]
             (let [nn (second decl)]
-              (reduce #(dep/depend %1 nn %2)
+              (reduce (fn [g dep] (dep/depend g nn dep))
                       ds (tns/deps-from-ns-decl decl))))
-          deps new-decls))
+          deps decls))

-(defn- update-deps [deps new-decls]
+(defn- update-deps [deps decls]
   (-> deps
-      (remove-deps new-decls)
-      (add-deps new-decls)))
+      (remove-deps decls)
+      (add-deps decls)))

-(defn- affected-namespaces [deps new-names]
+(defn- affected-namespaces [deps names]
   (apply set/union
-         (set new-names)
-         (map #(dep/transitive-dependents deps %) new-names)))
+         (set names)
+         (map #(dep/transitive-dependents deps %) names)))

 (defn tracker
   "Returns a new namespace dependency tracker."
@@ -59,9 +59,10 @@
   need to be reloaded after files were removed."
   [state files]
   (let [{:keys [load unload deps namespaces]} state
-        removed (keep (comp second namespaces) files)
-        new-deps (reduce dep/remove-key deps removed)
-        changed (affected-namespaces deps removed)]
+        removed-decls (keep namespaces files)
+        removed-names (map second removed-decls)
+        new-deps (remove-deps deps removed-decls)
+        changed (affected-namespaces deps removed-names)]
     (assoc state
       :namespaces (apply dissoc namespaces files)
       :deps new-deps
@@ -69,7 +70,7 @@
                (concat (reverse (sort (dep/topo-comparator deps) changed))
                        unload))
       :load (distinct
-             (filter (complement (set removed))
+             (filter (complement (set removed-names))
                      (concat (sort (dep/topo-comparator new-deps) changed)
                              load))))))


CLJS: remove dead code

CLJS: remove dead code

--- src/main/cljs/cljs/tools/reader.cljs
+++ src/main/cljs/cljs/tools/reader.cljs
@@ -687,11 +687,6 @@
   (or (instance? js/Boolean x)
       (true? x)
       (false? x)))
-
-(defn ^:private ns-name* [x]
-  (if (symbol? x)
-    (name x)
-    (name (ns-name x))))

 (defn ^:dynamic resolve-symbol
   "Resolve a symbol s into its fully qualified namespace version"


[core] Leave out local peer :name for now.

It muddies up the output visible in the terminal, and with user-supplied UUIDs
the human-readable name isn't important.

--- src/birdie_tell/core.clj
+++ src/birdie_tell/core.clj
@@ -297,7 +297,14 @@
              :uuid uuid ; my self-reference into [:peers :identified]
              :peers {:potential peer ; TODO: allow more than one potential peer
                      :identified {uuid {:version 0
-                                        :name name
+
+                                        ;; Leave :name out for now;
+                                        ;; it's not needed with
+                                        ;; user-supplied UUIDs, and
+                                        ;; fills up the screen too
+                                        ;; much.
+                                        ;; :name name
+
                                         :uuid uuid
                                         :host-port host-port}}})


end all files with newline

end all files with newline

--- src/java_time/fields.clj
+++ src/java_time/fields.clj
@@ -31,4 +31,4 @@
 (defonce julian
   {:julian-day          JulianFields/JULIAN_DAY
    :modified-julian-day JulianFields/MODIFIED_JULIAN_DAY
-   :rata-die            JulianFields/RATA_DIE})+   :rata-die            JulianFields/RATA_DIE})


Extended CLI tests.

Extended CLI tests.

--- test/leiningen/cli_test.clj
+++ test/leiningen/cli_test.clj
@@ -2,8 +2,10 @@
   (:require [midje.sweet :refer :all]
             [leiningen.ancient.utils.cli :refer :all]))

+(def DEFAULTS (parse-cli nil))
+
 (fact "about the default settings"
-  (parse-cli nil) =>
+  DEFAULTS =>
       {:aggressive?      false
        :check-clojure    false
        :dependencies     true
@@ -17,3 +19,21 @@
        :snapshots?       false
        :tests            true
        :verbose          false})
+
+(tabular
+  (fact "about flag effects"
+    (parse-cli ?args) => (apply assoc DEFAULTS ?effects))
+  ?args                     ?effects
+  [":plugins"]              [:dependencies false :plugins true]
+  [":all"]                  [:dependencies true  :plugins true]
+  [":interactive"]          [:interactive true]
+  [":allow-snapshots"
+   ":allow-qualified"]      [:snapshots? true :qualified? true]
+  [":aggressive"]           [:aggressive? true]
+  [":overwrite-backup"]     [:overwrite-backup true]
+  [":no-tests"]             [:tests false]
+  [":no-profiles"]          [:profiles false]
+  [":no-colors"]            [:no-colors true]
+  [":verbose"
+   ":check-clojure"
+   ":print"]                [:verbose true :check-clojure true :print true])


(FIX): build error

(FIX): build error

--- src/jjamppong/window.clj
+++ src/jjamppong/window.clj
@@ -8,6 +8,7 @@
    [clojure.reflect :as r]
    [clojure.string :as str]
    [named-re.re :as re]
+   [clojure.java.shell]
    [clojure.core.async :as async])

   (:import


vcs-type as equality constraint for add-projects + allow nil for icon

--- src-cljs/frontend/components/add_projects.cljs
+++ src-cljs/frontend/components/add_projects.cljs
@@ -37,16 +37,21 @@
 (defn organization [org settings owner]
   (let [login (:login org)
         type (if (:org org) :org :user)
-        vcs-type (:vcs_type org)]
-    [:li.organization {:on-click #(raise! owner [:selected-add-projects-org {:login login :type type}])
-                        :class (when (= {:login login :type type} (get-in settings [:add-projects :selected-org])) "active")}
+        vcs-type (:vcs_type org)
+        selected-org-view {:login login :type type :vcs-type vcs-type}]
+    [:li.organization {:on-click #(raise! owner [:selected-add-projects-org selected-org-view])
+                       :class (when (= selected-org-view (get-in settings [:add-projects :selected-org])) "active")}
      [:img.avatar {:src (gh-utils/make-avatar-url org :size 50)
             :height 50}]
      [:div.orgname login]
-     (if (= "github" vcs-type)
+     (cond
+       ;; TODO remove the nil check after a migration adds vcs-type to all entities
+       (contains? #{"github" nil} vcs-type)
        [:a.visit-org {:href (str (gh-utils/http-endpoint) "/" login)
                       :target "_blank"}
         [:i.octicon.octicon-mark-github]]
+
+       (= "bitbucket" vcs-type)
        [:a.visit-org
         [:i.fa.fa-bitbucket]])]))


Org plan settings to use enterprise ui flag

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -268,7 +268,7 @@
            [:div#edit-plan {:class "pricing.page"}
             (when (pm/piggieback? plan org-name)
               (plans-piggieback-plan-notification plan org-name))
-            (when-not (pm/enterprise? plan)
+            (when-not (config/enterprise?)
               [:fieldset
                [:legend (str "Our pricing is flexible and scales with you. Add as many containers as you want for $"
                              container-cost "/month each.")]])
@@ -286,7 +286,7 @@
                            :type "text" :value selected-containers
                            :on-change #(utils/edit-input owner state/selected-containers-path %
                                                          :value (int (.. % -target -value)))}]
-                  [:span.new-plan-total (str (pluralize-no-val selected-containers "container") (when-not (pm/enterprise? plan) (str " for " (if (= 0 new-total) "Free!" (str "$" new-total "/month")))))]
+                  [:span.new-plan-total (str (pluralize-no-val selected-containers "container") (when-not (config/enterprise?) (str " for " (if (= 0 new-total) "Free!" (str "$" new-total "/month")))))]
                   (when (not (= new-total old-total))
                     [:span.strikeout {:style {:margin "auto"}} (str "$" old-total "/month")])
                   (when false ;; (pm/grandfathered? plan) ;; I don't
@@ -294,7 +294,7 @@
                     [:i.fa.fa-question-circle#grandfathered-tooltip-hack
                      {:title "We've changed plan prices since you signed up, so you're grandfathered in at the old price!"}])]]
                 [:fieldset
-                 (if (and (pm/can-edit-plan? plan org-name) (or (pm/enterprise? plan) (pm/paid? plan)))
+                 (if (and (pm/can-edit-plan? plan org-name) (or (config/enterprise?) (pm/paid? plan)))
                    (forms/managed-button
                     [:button.btn.btn-large.btn-primary.center
                      {:data-success-text "Saved",
@@ -326,7 +326,7 @@
                                                                            (pluralize selected-containers "container"))}])
                                          false))}
                        "Pay Now"])))
-                 (when-not (pm/enterprise? plan)
+                 (when-not (config/enterprise?)
                    ;; TODO: Clean up conditional here - super nested and many interactions
                    (if (or (pm/paid? plan) (and (pm/freemium? plan) (not (pm/in-trial? plan))))
                      (list
@@ -864,7 +864,7 @@
               " for more parallelism and shorter queue times."))])
         (when (pm/freemium? plan)
           [:p (str (pm/freemium-containers plan) " container is free, forever.")])
-        (when-not (pm/enterprise? plan)
+        (when-not (config/enterprise?)
           [:p "Additionally, projects that are public on GitHub will build with " pm/oss-containers " extra containers -- our gift to free and open source software."])]]))))

 (def main-component


Updates reverse-string to 1.2.0

Updates reverse-string to 1.2.0

--- exercises/reverse-string/test/reverse_string_test.clj
+++ exercises/reverse-string/test/reverse_string_test.clj
@@ -20,6 +20,9 @@
 (deftest palindrome-test
   (is (= "racecar" (reverse-string/reverse-string "racecar"))))

+(deftest even-sized-word-test
+  (is (= "reward" (reverse-string/reverse-string "drawer"))))
+
 (deftest long-string-test
   (let [s (reduce str (repeat 1000 "overflow?"))
         rs (reduce str (repeat 1000 "?wolfrevo"))]


CMR-3999: Minor refactoring.

CMR-3999: Minor refactoring.

--- search-app/src/cmr/search/services/query_service.clj
+++ search-app/src/cmr/search/services/query_service.clj
@@ -308,7 +308,7 @@
   "Executes elasticsearch searches to find collections that have deleted revisions.
    Returns a list of concept-ids of the collections."
   [context params]
-  ;;1/ Find all collection revisions that are deleted satisfy the original search params
+  ;; Find all collection revisions that are deleted satisfying the original search params
   (let [query (make-concepts-query context :collection params)
         condition (gc/and-conds
                    [(:condition query)
@@ -355,8 +355,9 @@
                                   #(apply max (map :revision-id %))
                                   (group-by :concept-id (:items results)))
           highest-revisions (filter
-                             #((set highest-coll-revisions)
-                               [(:concept-id %) (:revision-id %)])
+                             (fn [coll]
+                               ((set highest-coll-revisions)
+                                [(:concept-id coll) (:revision-id coll)]))
                              (:items results))]
       (-> results
           (assoc :items highest-revisions)
@@ -364,12 +365,12 @@

 (defn get-deleted-collections
   "Executes elasticsearch searches to find collections that are deleted.
-   This only finds collections that are truely deleted and not searchable.
+   This only finds collections that are truly deleted and not searchable.
    Collections that are deleted, then later ingested again are not included in the result.
    Returns references to the highest collection revision prior to the collection tombstone."
   [context params]
   (pv/validate-deleted-collections-params params)
-  ;; 1/ Find all collection revisions that are deleted after satify the revision-date query -> c1
+  ;; 1/ Find all collection revisions that are deleted satisfying the revision-date query -> c1
   ;; 2/ Filters out any collections c1 that still exists -> c2
   ;; 3/ Find all collection revisions for the c2, return the highest revisions that are visible
   (let [start-time (System/currentTimeMillis)
@@ -384,7 +385,7 @@
         ;; when results is nil, hits is 0
         results (or results {:hits 0 :items []})
         total-took (- (System/currentTimeMillis) start-time)
-        ;; construt the response results string
+        ;; construct the response results string
         results-str (common-search/search-results->response
                      context
                      ;; pass in a fake query to get the desired response format


Prevent from querying for bearer token at compilation

--- src/clj/ozwiena/core.clj
+++ src/clj/ozwiena/core.clj
@@ -35,8 +35,10 @@
                   :content-type "application/x-www-form-urlencoded;charset=UTF-8"
                   :body "grant_type=client_credentials"})))

-(def bearer (:access_token (get-bearer (env :twitter-key)
-                                       (env :twitter-secret))))
+(let [key (env :twitter-key)
+      secret (env :twitter-secret)]
+  (def bearer (if (and key secret)
+                (:access_token (get-bearer key secret)))))

 (defn- log [msg & vals]
   (let [line (apply format msg vals)]


Use standard Clojure map for cookies (#621)

Clojure `sorted-map` and `sorted-set` are useful in some scenarios but can present problems in others:

* good: predictable iteration order, used to great effect in `apply-on-form-params`, `test-encode-cookies`, and `test-wrap-cookies`
* bad: `get`, `contains?`, `find`, `dissoc`, `select-keys`, etc throw ClassCastException when given incompatible keys https://clojure.atlassian.net/browse/CLJ-2693
* bad: `=` and `clojure.data/diff` can yield exceptions https://clojure.atlassian.net/browse/CLJ-2325 https://clojure.atlassian.net/browse/CLJ-1983
* bad: `pr` and `print` generate strings indistinguishable from unsorted map/set
* bad: `print-dup` generates unreadable strings https://clojure.atlassian.net/browse/CLJ-1733

I propose to avoid `sorted-map` for values in the clj-http `:cookies` map. Looking at the commit history, I'm unable to determine why a sorted-map was used initially. The change away from sorted-map doesn't break any tests and doesn't appear to have any substantive effect on clj-http behavior, but perhaps there are some use cases I'm not familiar with.

Of course, I probably should provide a justification or example of obvious downside to this use of sorted-map 😉  so I'll attempt to explain:

```clj
user> (-> resp pr-str clojure.edn/read-string (get-in [:cookies "someCookie" "value"])
nil
user> (-> resp pr-str clojure.edn/read-string (get-in [:cookies "someCookie" :value])
"someValue"

user> (-> resp (get-in [:cookies "someCookie" "value"])
ClassCastException clojure.lang.Keyword cannot be cast to java.lang.String java.lang.String.compareTo (String.java:111)
user> (-> resp (get-in [:cookies "someCookie" :value])
"someValue"
```

We expect `get` or `find` to return `nil` when a key isn't present in a map, and that's what we observe when serializing the response map from service1 to EDN and reading this EDN in service2. We were surprised when the same code threw ClassCastException when executed within service1.

While I wouldn't expect another clj-http user to run into exactly this set of circumstances, the potential for inconsistent behavior, this inconvenient behavior of sorted-map, the lack of obvious upside to using sorted-map for cookie values, and the minimal clj-http code change lead me to believe this is a worthwhile change.

In the meantime, we've adjusted our code to coerce these sorted-maps to standard Clojure maps, so I won't claim that we're blocked on this clj-http change. My goal here is to document the concern and attempt to make a case for this change, but remain open-minded about the approach and probably learn something in the process 😄

Happy to discuss alternatives, concerns, etc.

Thanks your ongoing maintenance and stewardship of clj-http @dakrone 😃

--- src/clj_http/cookies.clj
+++ src/clj_http/cookies.clj
@@ -22,7 +22,7 @@
             (if (not (nil? (get m k)))
               (assoc newm k (get m k))
               newm))
-          (sorted-map) (sort (keys m))))
+          {} (keys m)))

 (defn to-cookie
   "Converts a ClientCookie object into a tuple where the first item is


fix most tests

fix most tests

--- test/oi_lang/obj_tests.cljs
+++ test/oi_lang/obj_tests.cljs
@@ -1,28 +1,29 @@
 (ns oi-lang.obj-tests
-  (:require [cljs.test :as test :refer [is] :refer-macros [deftest]]))
+  (:require [cljs.test :as test :refer [is] :refer-macros [deftest]]
+            [oi-lang.obj :as oi]))

 (deftest simple-parses
-  (is (= (parse "42") [[:number 42]]))
-  (is (= (parse "\"foo\"") [[:string "foo"]]))
-  (is (= (parse "bar") [[:message "bar"]]))
-  (is (= (parse "bar()") [[:message "bar" [:arglist]]]))
-  (is (= (parse "bar(1)") [[:message "bar" [:arglist [:number 1]]]]))
-  (is (= (parse "bar(1, 2)") [[:message "bar" [:arglist [:number 1] [:number 2]]]]))
-  (is (= (parse "bar(1, 2, 3)") [[:message "bar" [:arglist [:number 1] [:number 2] [:number 3]]]]))
-  (is (= (parse "foo bar") [[:send [:message "foo"] [:message "bar"]]]))
-  (is (= (parse "foo < bar") [[:send [:message "foo"] [:message "<" [:arglist [:message "bar"]]]]]))
-  (is (= (parse "x := 42") [[:message "setSlot" [:arglist [:message "x"] [:number 42]]]])))
+  (is (= (oi/parse "42") [[:number 42]]))
+  (is (= (oi/parse "\"foo\"") [[:string "foo"]]))
+  (is (= (oi/parse "bar") [[:message "bar"]]))
+  (is (= (oi/parse "bar()") [[:message "bar" [:arglist]]]))
+  (is (= (oi/parse "bar(1)") [[:message "bar" [:arglist [:number 1]]]]))
+  (is (= (oi/parse "bar(1, 2)") [[:message "bar" [:arglist [:number 1] [:number 2]]]]))
+  (is (= (oi/parse "bar(1, 2, 3)") [[:message "bar" [:arglist [:number 1] [:number 2] [:number 3]]]]))
+  (is (= (oi/parse "foo bar") [[:send [:message "foo"] [:message "bar"]]]))
+  (is (= (oi/parse "foo < bar") [[:send [:message "foo"] [:message "<" [:arglist [:message "bar"]]]]]))
+  (is (= (oi/parse "x := 42") [[:message "setSlot" [:arglist [:message "x"] [:number 42]]]])))

 (deftest simple-ast->runtime*-tests
-  (is (oi-= (ast->runtime* (parse "42")) [(oi-number 42)]))
-  (is (oi-= (ast->runtime* (parse "42 < 22")) [oi-false]))
-  (is (oi-= (ast->runtime* (parse "2<1")) [oi-false]))
-  (is (oi-= (ast->runtime* (parse "1<2")) [oi-true]))
-  (is (oi-= (ast->runtime* (parse "42 > 22")) [oi-true])))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "42")) [(oi/oi-number 42)]))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "42 < 22")) [oi/oi-false]))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "2<1")) [oi/oi-false]))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "1<2")) [oi/oi-true]))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "42 > 22")) [oi/oi-true])))

 (deftest list-ast->runtime*-tests
-  (is (oi-= (ast->runtime* (parse "list(1, 2, 3)")) [(oi-list (oi-number 1) (oi-number 2) (oi-number 3))]))
-  (is (oi-= (ast->runtime* (parse "x := list(1, 2, 3); x")) [(oi-list (oi-number 1) (oi-number 2) (oi-number 3))])))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "list(1, 2, 3)")) [(oi/oi-list (oi/oi-number 1) (oi/oi-number 2) (oi/oi-number 3))]))
+  (is (oi/oi-= (oi/ast->runtime* (oi/parse "x := list(1, 2, 3); x")) [(oi/oi-list (oi/oi-number 1) (oi/oi-number 2) (oi/oi-number 3))])))

 (deftest simple-eval-tests
-  (is (oi-= (eval* (ast->runtime* (parse "42"))) [(oi-number 42)])))
+  (is (oi/oi-= (oi/eval* (oi/ast->runtime* (oi/parse "42"))) [(oi/oi-number 42)])))


include clojure as a dev dep

include clojure as a dev dep

--- storm-kafka/project.clj
+++ storm-kafka/project.clj
@@ -5,6 +5,7 @@
   :dependencies [[storm/kafka "0.6.0"
                    :exclusions [org.apache.zookeeper/zookeeper
                                 log4j/log4j]]]
-  :dev-dependencies [[storm "0.7.0"]]
+  :dev-dependencies [[storm "0.7.0"]
+                     [org.clojure/clojure "1.2.0"]]
   :jvm-opts ["-Djava.library.path=/usr/local/lib:/opt/local/lib:/usr/lib"]
 )


(PE-34383) Allow running with jdk 17 without warnings

--- src/puppetlabs/puppetdb/cli/util.clj
+++ src/puppetlabs/puppetdb/cli/util.clj
@@ -24,6 +24,7 @@
     (re-matches #"1\.[89]($|(\..*))" version) :deprecated
     (re-matches #"10($|(\..*))" version) :deprecated
     (re-matches (re-pattern (str supported-java-version "($|(\\..*))")) version) :official
+    (re-matches #"17($|(\..*))" version) :tested
     :else :unknown))

 (defn jdk-unsupported-msg [version]


Added second error value to String Differences problem

--- src/clojush/problems/software/string_differences.clj
+++ src/clojush/problems/software/string_differences.clj
@@ -142,24 +142,30 @@
         (the-actual-string-differences-error-function program data-cases false))
       ([program data-cases print-outputs]
         (let [behavior (atom '())
-              errors (doall
-                       (for [[[input1 input2] correct-output] (case data-cases
-                                                                :train train-cases
-                                                                :test test-cases
-                                                                [])]
-                         (let [final-state (run-push program
-                                                     (->> (make-push-state)
-                                                       (push-item input2 :input)
-                                                       (push-item input1 :input)
-                                                       (push-item "" :output)))
-                               result (stack-ref :output 0 final-state)]
-                           (when print-outputs
-                             (println (format "| Correct output: %s\n| Program output: %s\n" (pr-str correct-output) (pr-str result))))
-                           ; Record the behavior
-                           (when @global-print-behavioral-diversity
-                             (swap! behavior conj result))
-                           ; Error is Levenshtein distance of printed strings
-                           (levenshtein-distance correct-output result))))] ;;NOTE: SEE NOTE IN INTRO
+              errors (flatten (doall
+                                (for [[[input1 input2] correct-output] (case data-cases
+                                                                         :train train-cases
+                                                                         :test test-cases
+                                                                         [])]
+                                  (let [final-state (run-push program
+                                                              (->> (make-push-state)
+                                                                (push-item input2 :input)
+                                                                (push-item input1 :input)
+                                                                (push-item "" :output)))
+                                        result (stack-ref :output 0 final-state)]
+                                    (when print-outputs
+                                      (println (format "| Correct output: %s\n| Program output: %s\n" (pr-str correct-output) (pr-str result))))
+                                    ; Record the behavior
+                                    (when @global-print-behavioral-diversity
+                                      (swap! behavior conj result))
+                                    ; Error is:
+                                    ;   1. Levenshtein distance of printed strings
+                                    ;   2. Difference in number of lines using the correct format
+                                    (vector
+                                      (levenshtein-distance correct-output result)
+                                      (abs (- (count (re-seq #"(?m)^\d+ \S \S$" correct-output))
+                                              (count (re-seq #"(?m)^\d+ \S \S$" result))))
+                                      )))))] ;;NOTE: SEE NOTE IN INTRO
           (when @global-print-behavioral-diversity
             (swap! population-behaviors conj @behavior))
           errors)))))


Change data-test-id of deprecated component to match the new component (so the tests won't care which is used). (#943)

--- src/cljs/main/broadfcui/common/components.cljs
+++ src/cljs/main/broadfcui/common/components.cljs
@@ -631,7 +631,7 @@
 ;; Deprecated. If you are touching code that uses this, please migrate to use broadfcui.components.modals
 (defn push-error [content]
   (push-ok-cancel-modal
-   {:header [:div {:style {:display "inline-flex" :alignItems "center"} :data-test-id "push-error"}
+   {:header [:div {:style {:display "inline-flex" :alignItems "center"} :data-test-id "error-modal"}
              (icons/icon {:style {:color (:exception-state style/colors)
                                   :marginRight "0.5em"}} :error)
              "Error"]


support withClusterName in cluster builder

--- src/clojure/clojurewerkz/cassaforte/client.clj
+++ src/clojure/clojurewerkz/cassaforte/client.clj
@@ -116,6 +116,7 @@
            connections-per-host
            max-connections-per-host
            consistency-level
+           cluster-name
            retry-policy
            reconnection-policy
            load-balancing-policy
@@ -132,6 +133,8 @@
       (.withProtocolVersion builder (ProtocolVersion/fromInt protocol-version)))
     (when credentials
       (.withCredentials builder (:username credentials) (:password credentials)))
+    (when cluster-name
+      (.withClusterName builder cluster-name)
     (when connections-per-host
       (.setCoreConnectionsPerHost pooling-options HostDistance/LOCAL
                                   connections-per-host))


now we can iterate over each line set

now we can iterate over each line set

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -240,4 +240,8 @@

       ]

+  ;; map over each 6-line-set...
+  (doseq [line-set sorted-grouped-line-set-list]
+    (prn line-set))
+
   )


Use java.awt.Color instead of re-implementing conversions.

--- src/org/playasophy/wonderdome/util/color.clj
+++ src/org/playasophy/wonderdome/util/color.clj
@@ -1,90 +1,51 @@
 (ns org.playasophy.wonderdome.util.color
   "Functions for manipulating and generating color values.
-
-  See: http://en.wikipedia.org/wiki/HSL_and_HSV")
-
-
-;;;;; HELPER FUNCTIONS ;;;;;
-
-(defn float->byte
-  "Converts a number in the range [0.0, 1.0] to an integer in the range [0,
-  255]. Values outside this range will be clamped."
-  [value]
-  {:pre [(number? value)]}
-  (-> value (* 255) int (bit-and 0xFF)))
-
-
-(defn byte->float
-  "Converts a byte in the range [0, 255] to a floating-point value in the range
-  [0.0, 1.0]."
-  [value]
-  (-> value (bit-and 0xFF) (/ 255.0)))
-
+  See: http://en.wikipedia.org/wiki/HSL_and_HSV"
+  (import
+    java.awt.Color))

 ;;;;; RGB COLOR SPACE ;;;;;

 (defn rgb*
-  "Creates a color value compatible with Processing and PixelPusher hardware.
-  Each color channel should be an 8-bit value from 0 to 255. If not set, the
-  alpha channel defaults to full opacity (255)."
-  ([r g b]
-   (rgb* r g b 255))
-  ([r g b a]
-   {:pre [(integer? r) (integer? g) (integer? b) (integer? a)]}
-   (unchecked-int
-     (+ (bit-shift-left (bit-and 0xFF a) 24)
-        (bit-shift-left (bit-and 0xFF r) 16)
-        (bit-shift-left (bit-and 0xFF g)  8)
-                        (bit-and 0xFF b)))))
+  "Creates a color value from red, green, and blue component channels. Each
+  component should be an 8-bit value from [0, 255]."
+  [r g b]
+  (.getRGB (Color. (int r) (int g) (int b))))

 (defn rgb
-  "Creates a color value from red, green, and blue channel values. Each value
-  should be a number from [0.0, 1.0]."
+  "Creates a color value from red, green, and blue component channels. Each
+  component should be a number from [0.0, 1.0]."
   [r g b]
-  {:pre [(number? r) (number? g) (number? b)]}
-  (rgb*
-    (float->byte r)
-    (float->byte g)
-    (float->byte b)))
+  (.getRGB (Color. (float r) (float g) (float b))))

-(defn red
-  "Extracts the red channel from a color value. Returns a floating-point value
-  from [0.0, 1.0]."
+(defn rgb-components
+  "Takes a color value and returns a vector containing the red, green, and blue
+  component channels as floating-point numbers."
   [color]
-  {:pre [(integer? color)]}
-  (-> color (bit-shift-right 16) byte->float))
-
-
-(defn green
-  "Extracts the green channel from a color value. Returns a floating-point
-  value from [0.0, 1.0]."
-  [color]
-  {:pre [(integer? color)]}
-  (-> color (bit-shift-right 8) byte->float))
-
-
-(defn blue
-  "Extracts the blue channel from a color value. Returns a floating-point value
-  from [0.0, 1.0]."
-  [color]
-  {:pre [(integer? color)]}
-  (byte->float color))
+  (vec (.getRGBColorComponents (Color. (unchecked-int color)) nil)))

 ;;;;; HSV COLOR SPACE ;;;;;

 (defn hsv
-  "Creates a color value from a hue, saturation, and value. Hue is an angle in
-  [0.0, 2*PI], and saturation and value should be numbers from [0.0, 1.0]."
+  "Creates a color value from a hue, saturation, and value. The fractional
+  portion of the hue determines the angle in the HSV space; saturation and
+  value should be numbers from [0.0, 1.0]."
   [h s v]
-  ; TODO: implement HSV -> RGB conversion
-  nil)
+  ; TODO: document hue angles for pure red/green/blue
+  (Color/HSBtoRGB (float h) (float s) (float v)))

+(defn hsv-components
+  "Takes a color value and returns a vector containing the hue, saturation, and
+  value components as floating-point numbers."
+  [color]
+  (let [c (Color. (unchecked-int color))]
+    (vec (Color/RGBtoHSB (.getRed c) (.getBlue c) (.getGreen c) nil))))


Implementing Interface for Downing-Gallier, adding tests

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

--- src/conexp/contrib/algorithms/downing_gallier.clj
+++ src/conexp/contrib/algorithms/downing_gallier.clj
@@ -10,9 +10,9 @@
   (:use [conexp.base :only (not-yet-implemented, def-)]
         [conexp.fca.implications :only (premise conclusion)]))

-;;;
+;;; Implementation

-(defn implication-graph [base-set implications]
+(defn implication-graph [implications]
   (let [implications     (vec implications),
         where-in-premise (reduce (fn [map [i impl]]
                                    (reduce (fn [map m]
@@ -26,15 +26,14 @@
                                        (map (comp count premise) implications)))]
     [implications where-in-premise numargs]))

-(defn close-with-network [base-set implications input-set]
-  (let [[implications in-premise numargs] (implication-graph base-set implications),
-        numargs                           (reduce (fn [numargs i]
-                                                    (update-in numargs [i] dec))
-                                                  numargs
-                                                  (mapcat in-premise input-set))
-        empty-premise-implications        (map first
-                                               (filter (fn [[i c]] (zero? c))
-                                                       numargs))]
+(defn close-with-downing-gallier [[implications in-premise numargs] input-set]
+  (let [numargs                    (reduce (fn [numargs i]
+                                             (update-in numargs [i] dec))
+                                           numargs
+                                           (mapcat in-premise input-set))
+        empty-premise-implications (map first
+                                        (filter (fn [[i c]] (zero? c))
+                                                numargs))]
     (loop [queue   (into (clojure.lang.PersistentQueue/EMPTY)
                          empty-premise-implications),
            numargs numargs
@@ -54,20 +53,43 @@
               _ (println numargs)]
           (recur queue numargs (into result new)))))))

-;;;
+;;; Interface

-(do
+(defn clop-by-implications [implications]
+  (let [predata (implication-graph implications)]
+    (fn [input-set]
+      (close-with-downing-gallier predata input-set))))

-  (def- testing-implications #{(make-implication '#{p_3 p_4} '#{p_5})
-                               (make-implication '#{p_1} '#{p_2})
-                               (make-implication '#{p_2} '#{p_1})
-                               (make-implication '#{p_3} '#{p_4})
-                               (make-implication '#{}    '#{p_3})})
+(defn close-under-implications [implications input-set]
+  ((clop-by-implications implications) input-set))

-  (def- network (implication-graph '[p_1 p_2 p_3 p_4 p_5]
-                                   testing-implications))
+;;; Tests

-  nil)
+(require '[clojure.test :as test]
+         '[conexp.main :as conexp])
+
+(test/deftest test-close-under-implications
+  (test/are [start impls result]
+    (= result
+       (close-under-implications (map (partial apply make-implication)
+                                      impls)
+                                 start))
+    ;;
+    #{} [[#{} #{1}]] #{1},
+    #{1} [[#{1} #{2}] [#{2} #{3}] [#{3} #{4}] [#{4} #{5}]] #{1 2 3 4 5},
+    #{1 2 3} [[#{1 2} #{4}] [#{1 4} #{5}] [#{1 6} #{7}]] #{1 2 3 4 5}
+    #{1 2 3 4 5 6 7 8} [[#{1} #{4}] [#{2} #{3}] [#{4} #{5 6 7}] [#{6 7} #{8}] [#{9 10 11} #{8}]] #{1 2 3 4 5 6 7 8}))
+
+(test/deftest test-clop-by-implications
+  (let [clop (clop-by-implications #{(make-implication #{1} #{2}),
+                                     (make-implication #{3} #{4}),
+                                     (make-implication #{} #{1})})]
+    ;;
+    (test/is (= #{1 2} (clop #{1}) (clop #{2}) (clop #{})))
+    (test/is (= #{1 2 3 4} (clop #{3})))
+    (test/is (= #{1 2 4} (clop #{4})))
+    (test/is (= #{#{1 2} #{1 2 4} #{1 2 3 4}} (set (conexp/all-closed-sets [1 2 3 4] clop))))
+    (test/is (not= #{1 2 3 4} (clop #{1 2 4})))))

 ;;;


updated

updated

--- exercism/clojure/nucleotide-count/src/nucleotide_count.clj
+++ exercism/clojure/nucleotide-count/src/nucleotide_count.clj
@@ -1,13 +1,12 @@
 (ns nucleotide-count)

 (def base {\A 0 \C 0 \G 0 \T 0})
+(def base-keys (set (keys base)))

 (defn nucleotide-counts [dna]
-  (let [freqs (frequencies dna)
-        result (merge base freqs)]
-    (assert (= (keys base) (keys result)))
-    result))
+  {:post [(= base-keys (set (keys %)))]}
+  (merge-with + base (frequencies dna)))

 (defn count [s dna]
-  (assert (contains? base s))
+  {:pre [(base-keys s)]}
   ((nucleotide-counts dna) s 0))