Re-enable exit unit tests

Re-enable exit unit tests

--- planck-cljs/test/planck/repl_test.cljs
+++ planck-cljs/test/planck/repl_test.cljs
@@ -16,59 +16,67 @@
     (is (= [0 1] (js->clj (planck.repl/get-highlight-coords 2 "#{}" []))))
     (is (= [0 0] (js->clj (planck.repl/get-highlight-coords 4 "[\"[\"]" []))))))

-#_(deftest handle-error-non-exit-exception-non-exit-context
+(defonce planck-exit-nonterminate (js/PLANCK_GET_EXIT_VALUE))
+
+(deftest handle-error-non-exit-exception-non-exit-context
   (js/PLANCK_SET_EXIT_VALUE -1)
-  (let [result (planck.repl/handle-error (js/Error. "Original Error") false false)]
+  (let [result (binding [*print-fn* (constantly nil)]
+                 (planck.repl/handle-error (js/Error. "Original Error") false false))]
     (testing "Non-exit exception outside of exit context returns original error"
       (is (= "Original Error" (.-message result))))
     (testing "Non-exit exception outside of exit context preserves existing exit code"
       (is (= -1 (js/PLANCK_GET_EXIT_VALUE)))))
-  (js/PLANCK_SET_EXIT_VALUE 0))
+  (js/PLANCK_SET_EXIT_VALUE planck-exit-nonterminate))

-#_(deftest handle-error-exit-exception-non-exit-context
+(deftest handle-error-exit-exception-non-exit-context
   (js/PLANCK_SET_EXIT_VALUE 47)
-  (let [result (planck.repl/handle-error (js/Error. "PLANCK_EXIT") false false)]
+  (let [result (binding [*print-fn* (constantly nil)]
+                 (planck.repl/handle-error (js/Error. "PLANCK_EXIT") false false))]
     (testing "Exit exception outside of exit context returns original error"
       (is (= "PLANCK_EXIT" (.-message result))))
     (testing "Exit exception outside of exit context preserves existing exit code"
       (is (= 47 (js/PLANCK_GET_EXIT_VALUE)))))
-  (js/PLANCK_SET_EXIT_VALUE 0))
+  (js/PLANCK_SET_EXIT_VALUE planck-exit-nonterminate))

-#_(deftest handle-error-non-exit-exception-in-exit-context
+(deftest handle-error-non-exit-exception-in-exit-context
   (js/PLANCK_SET_EXIT_VALUE -1)
-  (let [result (planck.repl/handle-error (js/Error. "Original Error") false true)]
+  (let [result (binding [*print-fn* (constantly nil)]
+                 (planck.repl/handle-error (js/Error. "Original Error") false true))]
     (testing "Non-exit exception in exit context returns nothing"
       (is (= nil result)))
     (testing "Non-exit exception in exit context sets a default exit code"
       (is (= 1 (js/PLANCK_GET_EXIT_VALUE)))))
-  (js/PLANCK_SET_EXIT_VALUE 0))
+  (js/PLANCK_SET_EXIT_VALUE planck-exit-nonterminate))

-#_(deftest handle-error-exit-exception-in-exit-context
+(deftest handle-error-exit-exception-in-exit-context
   (js/PLANCK_SET_EXIT_VALUE 32)
-  (let [result (planck.repl/handle-error (js/Error. "PLANCK_EXIT") false true)]
+  (let [result (binding [*print-fn* (constantly nil)]
+                 (planck.repl/handle-error (js/Error. "PLANCK_EXIT") false true))]
     (testing "Exit exception in exit context returns exit error"
       (is (= "PLANCK_EXIT" (.-message result))))
     (testing "Exit exception in exit context preserves existing exit code"
       (is (= 32 (js/PLANCK_GET_EXIT_VALUE)))))
-  (js/PLANCK_SET_EXIT_VALUE 0))
+  (js/PLANCK_SET_EXIT_VALUE planck-exit-nonterminate))

-#_(deftest read-eval-print-exception-in-exit-context
+(deftest read-eval-print-exception-in-exit-context
   (js/PLANCK_SET_EXIT_VALUE 0)
-  (let [result (planck.repl/execute ["text" "(throw (js/Error. \"bye-bye\"))"] true false true nil true)]
+  (let [result (binding [*print-fn* (constantly nil)]
+                 (planck.repl/execute ["text" "(throw (js/Error. \"bye-bye\"))"] true false true nil true))]
     (testing "default exception return code as a side-effect"
       (is (= 1 (js/PLANCK_GET_EXIT_VALUE))))
     (testing "returns nothing"
       (is (= nil result))))
-  (js/PLANCK_SET_EXIT_VALUE 0))
+  (js/PLANCK_SET_EXIT_VALUE planck-exit-nonterminate))

-#_(deftest read-eval-print-exception-outside-exit-context
+(deftest read-eval-print-exception-outside-exit-context
   (js/PLANCK_SET_EXIT_VALUE 0)
-  (let [result (planck.repl/execute ["text" "(throw (js/Error. \"bye-bye\"))"] true false false nil true)]
+  (let [result (binding [*print-fn* (constantly nil)]
+                 (planck.repl/execute ["text" "(throw (js/Error. \"bye-bye\"))"] true false false nil true))]
     (testing "doesn't touch exit value"
       (is (= 0 (js/PLANCK_GET_EXIT_VALUE))))
     (testing "returns error"
       (is (not (= nil result)))))
-  (js/PLANCK_SET_EXIT_VALUE 0))
+  (js/PLANCK_SET_EXIT_VALUE planck-exit-nonterminate))

 (deftest test-apropos
   (is (= '(cljs.core/ffirst) (planck.repl/apropos "ffirst")))


More experimenting with event listeners.

--- ClojureScript/hello.cljs
+++ ClojureScript/hello.cljs
@@ -9,14 +9,14 @@

 (def pos (atom 0))

-(defn foobar [canvas]
+(defn foobar [canvas y]
     (let [ctx (.getContext canvas "2d")
         x (swap! pos inc)]
         (do
             (. ctx (save))
             (.clearRect ctx 0 0 (.width canvas) (.height canvas))
             (set! (.fillStyle ctx) "red")
-            (.fillRect ctx x 100 100 50)
+            (.fillRect ctx x y 100 50)
             (. ctx (restore))
             )))

@@ -29,7 +29,9 @@
             }) "")
         button (goog.dom/createDom "button" {} "Click!")]
         (do
-            (goog.events/listen button goog.events.EventType/CLICK (partial foobar canvas))
+            (goog.events/listen button goog.events.EventType/CLICK (partial foobar canvas 100))
+            (goog.events/listen document.body goog.events.EventType/KEYDOWN (partial foobar canvas 50) true)
+            (goog.events/listen document.body goog.events.EventType/KEYUP (partial foobar canvas 150) true)
             (dorun (map (partial goog.dom/appendChild document.body)
                 [(goog.dom/createDom "h1" {} "Hello!") canvas button])))))


Generalise list-rooms as list-things.

Generalise list-rooms as list-things.

--- src/isla/talk.clj
+++ src/isla/talk.clj
@@ -3,7 +3,7 @@
   (:require [clojure.string :as str])
   (:require [mrc.utils :as utils]))

-(declare list-rooms)
+(declare list-things)

 ;; look

@@ -42,15 +42,16 @@
 (defn room-already [name] (str "You are already in the " name "."))
 (defn room-not-allowed [name] (str "You cannot go into the " name "."))

-(defmulti list-rooms (fn [rooms] (count rooms)))
-(defmethod list-rooms 0 [rooms] "There is no way out of this room.")
-(defmethod list-rooms 1 [rooms] (str "You can see a door to the " (:name (first rooms)) "."))
-(defmethod list-rooms :default [rooms]
-  (let [all-room-list (reduce (fn [string x]
-                                (str string ", the " (:name x)))
-                              "" rooms)
-        all-but-last-list (rest (butlast (str/split all-room-list #",")))
-        final (str "You can see a door to"
+(defmulti list-things (fn [things zero one-intro many-intro article] (count things)))
+(defmethod list-things 0 [things zero one-intro many-intro article] zero)
+(defmethod list-things 1 [things zero one-intro many-intro article]
+  (str one-intro " " article " " (:name (first things)) "."))
+(defmethod list-things :default [things zero one-intro many-intro article]
+  (let [all-thing-list (reduce (fn [string x]
+                                (str string ", " article " " (:name x)))
+                              "" things)
+        all-but-last-list (rest (butlast (str/split all-thing-list #",")))
+        final (str many-intro
                    (str/join "," all-but-last-list)
-                   " and the " (:name (last rooms)) ".")]
-  final))
+                   " and " article " " (:name (last things)) ".")]
+    final))


Added integration tests for root routes.

--- dev-resources/src/cmr/opendap/dev.clj
+++ dev-resources/src/cmr/opendap/dev.clj
@@ -4,6 +4,7 @@
     [clojure.java.io :as io]
     [clojure.pprint :refer [pprint]]
     [clojure.set :as set]
+    [clojure.string :as string]
     [clojure.tools.namespace.repl :as repl]
     [clojusc.dev.system.core :as system-api]
     [clojusc.twig :as logger]


Rewrote some test text.

Rewrote some test text.

--- test-cljs/test.cljs
+++ test-cljs/test.cljs
@@ -132,7 +132,7 @@
       (is (= 2 (-> gamewithbothcharacters (gw/get-character testid2) defaultattack :damage))
            "Player 2's default attack does two damage")

-            (is (= 3 (gethealth gamewithbothcharacters testid2)) "Second character starts with 3 health before the attack")
+            (is (= 3 (gethealth gamewithbothcharacters testid2)) "Character 2 starts with 3 health before the attack")
       (is (= 2 (-> gamewithbothcharacters
                    (attack testid1 testid2)
                    (gethealth testid2))) "Character 1 attacks character 2, reducing character 2's health from 3 to 2")


Hide dataview by default

Hide dataview by default

--- src/app/ctl.cljs
+++ src/app/ctl.cljs
@@ -10,7 +10,7 @@

 (def import-visible? (atom false))
-(def dataview-visible? (atom true))
+(def dataview-visible? (atom false))

 (defn start [eventbus-in]


Have a basic schema working saving a deal and returnins all deals

--- src/gps/data.clj
+++ src/gps/data.clj
@@ -1,4 +1,5 @@
 (require '[datomic.api :as d])
+(require '[geohash.core :as geohash])

 (def uri "datomic:mem://gps")

@@ -62,42 +63,6 @@

 @(d/transact conn schema)

-(def first-transact
-  (datomic.api/transact conn
-                        [{
-                          :db/id #db/id[:db.part/user -1000001]
-                          :vendor/name "Quick deals"
-                          :vendor/deal "Buy one get one free"}
-                         {:db/id #db/id [:db.part/user -1000002]
-                          :location/vendor #db/id[:db.part/user -1000001]
-                          :location/geocode "abcfwert2asr"
-                          :location/lat 50.21345123
-                          :location/lon -6.32567134}
-                         ]))
-
-
-;; now let get the database value
-(def dbval (d/db conn))
-
-;; Query for the new hash value
-(def q-result (d/q '[:find ?e
-                     :where [?e :vendor/name] ]
-                   dbval))
-
-;; The result
-(count  q-result)
-
-;; Turn this into an entity to get its properties etc
-(def ent (d/entity dbval (ffirst q-result)))
-
-(keys  ent)
-(vals ent)
-
-(println  (:location/vendor ent))
-(:db/doc ent)
-
-(require '[geohash.core :as geohash])
-
 (defn save-deal[lat lon vendor-name deal-txt]
   (let [vendor-tmp-id (datomic.api/tempid :db.part/user)
         location-tmp-id (datomic.api/tempid :db.part/user)
@@ -114,3 +79,29 @@
              :location/lon ~lon}])))

 (save-deal 53.98193516 -6.41601562 "Dundalk shop" "Free coffee")
+
+
+(defn show-all-deals[]
+  (let [results (d/q '[:find ?e :where [?e :location/geocode]] (d/db conn))]
+    (doseq[r results]
+      (let [location-ent (d/entity dbval (first r))
+            vendor-ent (first (:location/vendor location-ent))
+            geocode (:location/geocode location-ent)
+            lat (:location/lat location-ent)
+            lon (:location/lon location-ent)
+            vendor-name (:vendor/name vendor-ent)
+            vendor-deal (:vendor/deal vendor-ent)]
+        (println "-----------------------------------")
+        (println (str "geocode: " geocode))
+        (println (str "lat:     " lat))
+        (println (str "lon:     " lon))
+        (println (str "Vendor:  " vendor-name))
+        (println (str "Deal:    " vendor-deal))
+        (println)))))
+
+
+
+(show-all-deals)
+
+
+(d/delete-database uri)


forbid read/write in single invocation

forbid read/write in single invocation

--- src/nml/core.clj
+++ src/nml/core.clj
@@ -126,6 +126,7 @@
   (let [{:keys [options arguments summary]} (cli/parse-opts args cliopts)
         filename (first arguments)
         tree (nmltree filename)]
+    (if (and (:get options) (:set options))(fail "Separate invocations required for read and write operations"))
     (println (str "### options " options))
     (println (str "### arguments " arguments))
     (println (str "### summary " summary))


Right, this time, I've got it

Right, this time, I've got it

--- src/onix/web.clj
+++ src/onix/web.clj
@@ -109,7 +109,7 @@
   (->
    (persistence/list-applications)
    sort
-   (hash-map :applications)
+   ((fn [a] {:applications a}))
    (response json-content-type)))

 (defn- get-application


Split up steps on add-projects

Split up steps on add-projects

--- frontend/components/add_projects.cljs
+++ frontend/components/add_projects.cljs
@@ -41,7 +41,8 @@
         [:a {:on-click #(put! ch [:selected-add-projects-org {:login login :type type}])} login]]
        [:small.github-url.pull-right
         [:a {:href "http://github.com"}
-         [:i.fa.fa-github-alt ""]]]
+         [:i.fa.fa-github-alt ""]
+         ]]
        [:div
         "12 projects"
         " • "
@@ -62,16 +63,17 @@
             [:div.overview
              [:p
               "Choose a repo in GitHub from one of your organizations, your own repos, or repos you share with others, and we'll watch it for you. We'll show you the first build immediately, and a new build will be initiated each time someone pushes commits; come back here to follow more projects."]]
-               (map (fn [org] (side-item org settings controls-ch))
-                    (:organizations user))
-               (map (fn [org] (side-item org settings controls-ch))
-                    (filter (fn [org] (= (:login user) (:login org)))
-                            (:collaborators user)))
-               [:div
-                [:h3 "Users & organizations with forks of your repos"]
-                (map (fn [org] (side-item org settings controls-ch))
-                     (remove (fn [org] (= (:login user) (:login org)))
-                             (:collaborators user)))]])))))
+            [:div.wordy-hr [:span "1. Choose a GitHub Account"]]
+            (map (fn [org] (side-item org settings controls-ch))
+                  (:organizations user))
+            (map (fn [org] (side-item org settings controls-ch))
+                  (filter (fn [org] (= (:login user) (:login org)))
+                          (:collaborators user)))
+             [:div
+              [:h4 "Users & organizations with forks of your repos"]
+              (map (fn [org] (side-item org settings controls-ch))
+                   (remove (fn [org] (= (:login user) (:login org)))
+                           (:collaborators user)))]])))))

 (def repos-explanation
   [:div.add-repos
@@ -103,9 +105,7 @@
                 [:div.proj-name
                  [:span {:title (str (vcs-url/project-name (:vcs_url repo))
                                      (when (:fork repo) " (forked)"))}
-                  (:name repo)]
-                 (when (:fork repo)
-                   [:span.forked (str " (" (vcs-url/org-name (:vcs_url repo)) ")")])]
+                  (:name repo)]]
                 (when building?
                   [:div.building "Starting first build..."])
                 (stateful-button
@@ -178,8 +178,8 @@
             controls-ch (om/get-shared owner [:comms :controls])]
         (html
          [:div.repo-filter
-          [:i.fa.fa-search]
-          [:input.unobtrusive-search.input-large
+          ; [:i.fa.fa-search]
+          [:input.unobtrusive-search
            {:placeholder "Filter repos..."
             :type "search"
             :value repo-filter-string
@@ -201,6 +201,7 @@
             (if-not (seq repos)
               [:div.loading-spinner common/spinner]
               [:ul.proj-list
+               [:li.filter (om/build repo-filter settings)]
                (let [filtered-repos (filter (fn [repo]
                                               (-> repo
                                                   :name
@@ -236,10 +237,7 @@
             (om/build org-sidebar {:user user
                                    :settings settings})]
            [:div.project-listing
-            [:hr]
-
-            (om/build repo-filter settings)
-
+            [:div.wordy-hr [:span "2. Choose a Repo"]]
             (om/build main {:user user
                             :repos repos
                             :settings settings})]


More sauce content

More sauce content


Follow kibit recommendation.

Follow kibit recommendation.

--- src/incise/core.clj
+++ src/incise/core.clj
@@ -16,7 +16,7 @@
   [["-h" "--help" "Print this help."]
    ["-m" "--method METHOD" "serve, once, or deploy"
     :default :serve
-    :parse-fn #(keyword %)
+    :parse-fn keyword
     :validate [#(contains? valid-methods %)
                "method must be either serve, once or deploy"]]
    ["-c" "--config CONFIG_FILE"


Correct grammar/spelling

Correct grammar/spelling

* the past participle of 'run' is 'run', not 'ran'.

--- src/metabase/db.clj
+++ src/metabase/db.clj
@@ -112,7 +112,7 @@
 (def ^:private ^:const ^String changelog-file "liquibase.yaml")

 (defn- migrations-sql
-  "Return a string of SQL containing the DDL statements needed to perform unran LIQUIBASE migrations."
+  "Return a string of SQL containing the DDL statements needed to perform unrun LIQUIBASE migrations."
   ^String [^Liquibase liquibase]
   (let [writer (StringWriter.)]
     (.update liquibase "" writer)
@@ -130,8 +130,8 @@
                        (re-find #"^--" line)))]
     line))

-(defn- has-unran-migrations?
-  "Does LIQUIBASE have migration change sets that haven't been ran yet?
+(defn- has-unrun-migrations?
+  "Does LIQUIBASE have migration change sets that haven't been run yet?

    It's a good idea to Check to make sure there's actually something to do before running `(migrate :up)` because `migrations-sql` will
    always contain SQL to create and release migration locks, which is both slightly dangerous and a waste of time when we won't be using them."
@@ -153,15 +153,15 @@
       (throw (Exception. "Database has migration lock; cannot run migrations. You can force-release these locks by running `java -jar metabase.jar migrate release-locks`.")))))

 (defn- migrate-up-if-needed!
-  "Run any unran LIQUIBASE migrations, if needed.
+  "Run any unrun LIQUIBASE migrations, if needed.

    This creates SQL for the migrations to be performed, then executes each DDL statement.
    Running `.update` directly doesn't seem to work as we'd expect; it ends up commiting the changes made and they can't be rolled back at
    the end of the transaction block. Converting the migration to SQL string and running that via `jdbc/execute!` seems to do the trick."
   [conn, ^Liquibase liquibase]
-  (log/info "Checking if Database has unran migrations...")
-  (when (has-unran-migrations? liquibase)
-    (log/info "Database has unran migrations. Waiting for migration lock to be cleared...")
+  (log/info "Checking if Database has unrun migrations...")
+  (when (has-unrun-migrations? liquibase)
+    (log/info "Database has unrun migrations. Waiting for migration lock to be cleared...")
     (wait-for-migration-lock-to-be-cleared liquibase)
     (log/info "Migration lock is cleared. Running migrations...")
     (doseq [line (migrations-lines liquibase)]
@@ -178,7 +178,7 @@
    Each DDL statement is ran inside a nested transaction; that way if the nested transaction fails we can roll it back without rolling back the entirety of changes
    that were made. (If a single statement in a transaction fails you can't do anything futher until you clear the error state by doing something like calling `.rollback`.)"
   [conn, ^Liquibase liquibase]
-  (when (has-unran-migrations? liquibase)
+  (when (has-unrun-migrations? liquibase)
     (doseq [line (migrations-lines liquibase)]
       (log/info line)
       (jdbc/with-db-transaction [nested-transaction-connection conn]


Clean up connect fn

Clean up connect fn

--- src/mpd/socket.cljs
+++ src/mpd/socket.cljs
@@ -37,14 +37,14 @@
   ([port] (connect port "localhost"))
   ([port host]
      (let [socket (new net.Socket)
-           [opener buffer] (repeatedly 2 chan)
+           buffer (chan)
            write (chan (dropping-buffer 1))
            read (chan (sliding-buffer 1))
            socket-chan
            (reify
              proto/ReadPort
              (take! [_ fn-handler]
-               (proto/take! read fn-handler false))
+               (proto/take! read fn-handler))
              proto/WritePort
               (put! [_ val fn-handler]
                 (proto/put! write val fn-handler))


Stop using multimethods on spec constructors.

--- src/octet/spec.cljc
+++ src/octet/spec.cljc
@@ -33,9 +33,7 @@
   (:refer-clojure :exclude [type read float double long short byte bytes repeat])
   (:require [octet.buffer :as buffer]))

-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Abstraction definition
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; --- Protocols

 (defprotocol ISpec
   "Basic abstraction for something that can be work like a Spec."
@@ -50,9 +48,7 @@
   "Abstraction for calculate size for dynamic specs."
   (size* [_ data] "Calculate the size in bytes of the object having a data."))

-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Composed Spec Types
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; --- Composed Spec Types

 (deftype AssociativeSpec [data dict types]
   #?@(:clj
@@ -140,11 +136,20 @@
      (alter-meta! #'->AssociativeSpec assoc :private true)
      (alter-meta! #'->IndexedSpec assoc :private true)))

-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Spec Constructors
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defmulti spec
+;; --- Spec Constructors
+
+(defn- associative-spec
+  [& params]
+  (let [data (mapv vec (partition 2 params))
+        dict (into {} data)
+        types (map second data)]
+    (AssociativeSpec. data dict types)))
+
+(defn- indexed-spec
+  [& types]
+  (IndexedSpec. types))
+
+(defn spec
   "Polymorphic constructor for Spec instances.

   Spec is a some kind of composition of arbitrary
@@ -171,27 +176,19 @@

   The same rules applies for writing data into a
   buffer."
-  (fn [& params]
-    (let [numparams (count params)]
-      (cond
-        (every? #(satisfies? ISpec %) params)
-        :indexed
-
-        (and (even? numparams)
-             (keyword? (first params))
-             (satisfies? ISpec (second params)))
-        :associative))))
-
-(defmethod spec :associative
   [& params]
-  (let [data (mapv vec (partition 2 params))
-        dict (into {} data)
-        types (map second data)]
-    (AssociativeSpec. data dict types)))
-
-(defmethod spec :indexed
-  [& types]
-  (IndexedSpec. types))
+  (let [numparams (count params)]
+    (cond
+      (every? #(satisfies? ISpec %) params)
+      (apply indexed-spec params)
+
+      (and (even? numparams)
+           (keyword? (first params))
+           (satisfies? ISpec (second params)))
+      (apply associative-spec params)
+
+      :else
+      (throw (ex-info "Invalid arguments" {})))))

 (defn repeat
   "Creare a composed typespec that repeats `n` times


[#1957] Don't expect only 2 authentication systems

--- backend/src/akvo/lumen/endpoint/env.clj
+++ backend/src/akvo/lumen/endpoint/env.clj
@@ -4,11 +4,12 @@
             [clojure.spec.alpha :as s]
             [clojure.tools.logging :as log]
             [integrant.core :as ig]
+            [akvo.lumen.specs :as lumen.s]
             [ring.util.response :as response]))

 (def auth-data (juxt :url :client-id))

-(s/def ::auth-type #{"keycloak" "auth0"})
+(s/def ::auth-type ::lumen.s/non-empty-string)

 (defn handler
   [{:keys [public-client flow-api lumen-deployment-color lumen-deployment-environment


Added selection of nodes + cleanup of drawing nodes.

--- evermind.web/src/evermind/web/core.cljs
+++ evermind.web/src/evermind/web/core.cljs
@@ -1,11 +1,11 @@
 (ns evermind.web.core
- (:require [om.core :as om :include-macros true]
-           [om.dom :as dom :include-macros true]
-           [evermind.domain.core :as d]))
+ (:require-macros [cljs.core.async.macros :refer [go]])
+ (:require [cljs.core.async :refer [put! chan <!]]
+           [evermind.domain.core :as d]
+           [om.core :as om :include-macros true]
+           [om.dom :as dom :include-macros true]))

 (enable-console-print!)
-
-(println "This text is printed from src/evermind.web/core.cljs. Go ahead and edit it and see reloading in action.")

 ;; define your app data so that it doesn't get over-written on reload

@@ -29,39 +29,86 @@
 (defn node-to-string [node]
       (-> node :attributes :text))

-(defn position-children [depth top bottom children]
-      (let [c (count children)
-            box-height (/ (- bottom top) c)
-            d (+ 1 depth)]
-           (map-indexed (fn [i n]
-                            (let [t (+ top (* box-height i))
-                                  b (+ t box-height)]
-                                 {:depth  d
-                                  :node   n
-                                  :x      (* d 10)
-                                  :y      (+ t (/ (- b t) 2))
-                                  :top    t
-                                  :bottom b
-                                  :text   (node-to-string n)}))
-                        children)))
+(defn update-node-position
+  [depth top bottom node]
+  (update-in node [:visu]
+    (fn [c] {:x (* depth 20)
+             :y (+ top (/ (- bottom top) 2))})))
+
+(defn update-node
+  ([root]
+   (update-node 0 0 0 100 root))
+  ([depth index top bottom node]
+   (let [newnode (update-node-position depth top bottom node)
+         c (count (:children node))
+         box-height (/ (- bottom top) c)
+         d (inc depth)]
+     (update-in newnode [:children]
+       (fn [children]
+           (map-indexed
+             (fn [i c]
+              (let [t (+ top (* box-height i))
+                    b (+ t box-height)]
+               (update-node d i t b c)))
+             children))))))

 (defn node-view [node owner]
-      (reify
-        om/IRender
-        (render [this]
-                (dom/g #js {:key (str "group-" (:key node))}
-                       (dom/text #js {:fill "black" :font-size "10px" :x (:x node) :y (:y node)}
-                                 (:text node))
-                       (om/build-all node-view
-                                     (position-children (+ 1 (:depth node)) (:top node) (:bottom node) (:children (:node node))))))))
+  (reify
+    om/IInitState
+    (init-state [state]
+      {:select (:select state)})
+    om/IRenderState
+    (render-state [this {:keys [select]}]
+        (dom/g #js {:key (str "group-" (:key node))}
+          (dom/text #js {:onClick (fn [e] (put! select node))
+                         :fontSize "3pt"
+                         :fill (if (-> node :attributes :selected) "red" "black")
+                         :x (-> node :visu :x)
+                         :y (-> node :visu :y)}
+                    (-> node :attributes :text))
+          (om/build-all node-view
+                        (:children node)
+                        {:init-state {:select select}
+                         :key :id})))))
+
+(defn update-node-selection [node selected]
+  (if (== (-> node :id) (-> selected :id))
+    (update-in node [:attributes]
+               (fn [v]
+                 (assoc v :selected true)))
+    (update-in node [:attributes]
+               (fn [v]
+                 (assoc v :selected false)))))
+
+(defn select-node [node selected]
+  (let [updated-node (update-node-selection node selected)]
+    (update-in updated-node [:children]
+               (fn [children]
+                 (mapv
+                   (fn [c] (select-node c selected))
+                   children)))))
+

 (defn mindmap-view [data owner]
-      (reify
-        om/IRender
-        (render [this]
-                (dom/div nil
-                         (dom/svg #js {:id "mindmap-svg" :viewBox "0 0 100 100"}
-                                  (om/build-all node-view (position-children 1 0 100 [(:mindmap data)])))))))
+  (reify
+    om/IInitState
+    (init-state [_]
+       {:select (chan)})
+    om/IWillMount
+    (will-mount [_]
+       (let [select (om/get-state owner :select)]
+         (go (loop []
+               (let [selected (<! select)]
+                  (om/transact! data [:mindmap]
+                                (fn [m]
+                                  (select-node m selected)))
+                  (recur))))))
+    om/IRenderState
+    (render-state [this {:keys [select]}]
+        (let [mindmap (update-node (:mindmap data))]
+          (dom/div nil
+            (dom/svg #js {:id "mindmap-svg" :viewBox "0 0 100 100"}
+              (om/build node-view mindmap {:init-state {:select select}})))))))

 (om/root mindmap-view app-state {:target (. js/document (getElementById "app"))})


Scheduler debugged

Scheduler debugged

--- slackbot/src/org/teamweek/slackbot.clj
+++ slackbot/src/org/teamweek/slackbot.clj
@@ -8,6 +8,7 @@
             [clojurewerkz.quartzite.jobs :as jobs :refer (defjob)]
             [clojurewerkz.quartzite.triggers :as triggers]
             [clojurewerkz.quartzite.schedule.cron :as cron]
+            [clojurewerkz.quartzite.conversion :as conversion]
             [byte-streams])
   (:gen-class))

@@ -53,8 +54,6 @@
       (throw (ex-info "Unable to connect" first-msg)))
     (keep-alive conn shutdown?)
     conn))
-
-

 (defn connect [token]
   (let [conn-data (-> (str "https://slack.com/api/rtm.start?token=" token)
@@ -124,13 +123,13 @@
         dm-sub (async/sub dm-pub username answer-chan)
         qas (reduce
              (fn [question-answers question]
-               (send-to-user! conn username question)
+               (send-to-user! conn username (:question/text question))
                (conj question-answers
                      {:ts (java.util.Date.)
                       :team (:name (:team conn))
                       :domain (:domain (:team conn))
                       :user username
-                      :question question
+                      :question-id (:db/id question)
                       :answer (:text (async/<!! answer-chan))}))
              []
              questions)]
@@ -143,9 +142,9 @@
   ;; TODO insert into datomic db
   (let [db (d/db db-conn)
         user-eid (d/q '[:find ?member .
-                        :in $ domain user
+                        :in $ ?domain ?user
                         :where
-                        [?team :team/domain domain]
+                        [?team :team/domain ?domain]
                         [?team :team/members ?member]
                         [?member :member/name ?user]]
                       db domain user)
@@ -154,11 +153,13 @@
               :answer/author user-eid
               :answer/text (:answer answer)
               :answer/ts (:ts answer)
-              :_question/answers (:question answer)})]
+              :question/_answers (:question-id answer)})]
+    (prn tx)
     @(d/transact db-conn tx)))

-(defjob QuestionnaireJob [{:keys [domain db-conn]}]
-  (let [db (d/db db-conn)
+(defjob QuestionnaireJob [job-data]
+  (let [{:strs [domain db-conn]} (conversion/from-job-data job-data)
+        db (d/db db-conn)
         token (:team/token (d/entity db [:team/domain domain]))
         users (d/q '[:find [?name ...]
                      :in $ ?domain
@@ -167,7 +168,7 @@
                      [?team :team/members ?member]
                      [?member :member/name ?name]]
                    db domain)
-        questions (d/q '[:find (pull ?question [:db/id :question/text])
+        questions (d/q '[:find [(pull ?question [:db/id :question/text :question/order]) ...]
                          :in $ ?domain
                          :where
                          [?team :team/domain ?domain]
@@ -180,8 +181,9 @@
     (if conn
       ;; TODO in parallell, but the job is not finished before all has answered/timeout
       (doseq [user users]
-        (let [answers (send-questionnaire conn user questions)]
-          (submit-answers db-conn domain user answers)))
+        (let [answers (send-questionnaire conn user (sort-by :question/order questions))]
+          (submit-answers db-conn domain user answers))
+        ((:shutdown-fn conn)))
       (do (println "Nothing to do")
           (println "Token" token) ;; TODO proper logging!
           (println "Users" users)
@@ -198,18 +200,21 @@
                  (triggers/with-schedule
                    (cron/schedule
                     (cron/cron-schedule cron-string))))]
-    (scheduler/schedule scheduler job trigger)))
+    (scheduler/schedule scheduler job trigger)
+    (println "Scheduler is running")))

 (defn init-start-jobs [scheduler db-conn]
-  (doseq [db (d/db db-conn)
-          {:keys [domain schedule]} (d/q '[:find (pull ?team [:team/domain :team/schedule])
-                                           :where
-                                           [?team :team/domain]]
-                                         db)]
-    (schedule-questionnaire-job scheduler
-                                db-conn
-                                domain
-                                schedule)))
+  (let [db (d/db db-conn)]
+    (doseq [{:keys [team/domain team/schedule]}
+            (d/q '[:find [(pull ?team [:team/domain :team/schedule]) ...]
+                   :where
+                   [?team :team/domain]]
+                 db)]
+      (println "Scheduling" domain schedule)
+      (schedule-questionnaire-job scheduler
+                                   db-conn
+                                   domain
+                                   schedule))) )

 (defn schedule-new [schduler db-before db-after]
   (let [new-domains (d/q '[:find [?new-domains ...]
@@ -276,20 +281,28 @@
   ;; db stuff

   (def db-uri "datomic:free://localhost:4334/teamweek")
+  (-main db-uri)
+

   (d/delete-database db-uri)
   (d/create-database db-uri)

   (def db-conn (d/connect db-uri))

+  (d/q '[:find (pull ?answer [:answer/author :answer/text :answer/ts])
+         :where
+         [?answer :answer/text]]
+       (d/db db-conn))
+
+
   (d/transact db-conn (read-string (slurp "../webapp/resources/schema.edn")))

   (future (listen-for-team-updates nil db-conn))

-  (defn create-team [team-name slack-token schedule-string members questions]
+  (defn create-team [domain slack-token schedule-string members questions]
     {:db/id (d/tempid :db.part/user)
-     :team/domain team-name
+     :team/domain domain
      :team/token slack-token
      :team/schedule schedule-string
      :team/members (for [[name email] members]
@@ -298,22 +311,16 @@
      :team/questions (for [text questions]
                        {:question/text text})})

-  (d/transact db-conn [(create-team "abc" "fdiosjfsodij" "* * * * *"
-                                    [["jonas" "jonas@gmail"]]
-                                    ["Who are you?"
-                                     "Where are you?"
-                                     "Where are you going?"])])
-
-  (d/transact db-conn [(create-team "def" "fdsoifjsidojf" "* * * * *"
-                                    [["ivan" "ivan@gmail"]
-                                     ["john" "doe@gmail"]]
-                                    ["What is your age?"])])
-
-  (d/transact db-conn [[:db.fn/retractEntity [:team/domain "def"]]])
-
-  (d/transact db-conn [[:db/add [:team/domain "abc"] :team/schedule "* * F * *"]])
-
-  (d/pull (d/db db-conn) [:team/domain :team/schedule] [:team/domain "abc"])
+  (def every-minute "0 * * * * ?")
+
+  (d/transact db-conn [(create-team "teamweek-org" slack-token every-minute
+                                    [#_["jonas" "jonas@gmail"]
+                                     ["ivan" "ivan@gmail"]]
+                                    ["How are you today?"
+                                     "What are your plans for tomorrow?"])])
+
+  (d/transact db-conn [[:db.fn/retractEntity [:team/domain "teamweek-org"]]])
+


Only capture direct messages

Only capture direct messages

--- slackbot/src/org/teamweek/slackbot.clj
+++ slackbot/src/org/teamweek/slackbot.clj
@@ -27,11 +27,15 @@
     username
     (throw (ex-info "No such user" {:user-id user-id}))))

+(defn direct-message? [msg]
+  (.startsWith (:channel msg) "D"))
+
 (defn route-messages [conn incoming-messages]
   (future (while true
             (let [msg (json/parse-string @(stream/take! (:ws-conn conn)) true)]
               (condp = (:type msg)
-                "message" (when-not (= (:user msg) (:id (:self conn)))
+                "message" (when (and (not= (:user msg) (:id (:self conn)))
+                                     (direct-message? msg))
                             (async/put! incoming-messages
                                         (assoc msg
                                                :username (find-username conn (:user msg)))))
@@ -99,9 +103,6 @@
                                        :channel (find-channel-id conn channel)
                                        :text msg})))

-
-
-
 (defn send-questionnaire
   [conn username questions]
   (send-to-user! conn username


[frontend] Fix warning about unknown variable.

--- src-cljs/pepa/components/document.cljs
+++ src-cljs/pepa/components/document.cljs
@@ -97,7 +97,7 @@
           document-date (:document-date document)
           str-value (when document-date (format-date document-date))]
       (if-not editing?
-        [:span.value.editable {:key "value", :title (str value)
+        [:span.value.editable {:key "value", :title str-value
                                :on-click (fn [e]
                                            (when supported?
                                              (om/set-state! owner :editing? true)))}


[#1949] Refactor: add `:pre` conditions to ids arg in auth calls

--- backend/src/akvo/lumen/lib/auth.clj
+++ backend/src/akvo/lumen/lib/auth.clj
@@ -23,26 +23,39 @@

 (declare ids)

+(defn- optimistic-allow?* [this ids]
+  {:pre [(= #{:dataset-ids :visualisation-ids :dashboard-ids :collection-ids}
+              (set (keys ids)))]}
+  (set/subset? (set/union (:dataset-ids ids) (:visualisation-ids ids)
+                            (:dashboard-ids ids) (:collection-ids ids))
+                 (set/union (:auth-datasets-set this) (:auth-visualisations-set this)
+                            (:auth-dashboards-set this) (:auth-collections-set this))))
+
+(defn- allow?* [this ids]
+  {:pre [(= #{:dataset-ids :visualisation-ids :dashboard-ids :collection-ids}
+              (set (keys ids)))]}
+  (and (set/subset? (:visualisation-ids ids) (:auth-visualisations-set this))
+       (set/subset? (:dataset-ids ids) (:auth-datasets-set this))
+       (set/subset? (:dashboard-ids ids) (:auth-dashboards-set this))
+       (set/subset? (:collection-ids ids) (:auth-collections-set this))))
+
+(defn- auth* [this ids]
+  {:pre [(= #{:dataset-ids :visualisation-ids :dashboard-ids :collection-ids}
+            (set (keys ids)))]}
+  {:auth-datasets       (set/intersection (:auth-datasets-set this) (set (:dataset-ids ids)))
+   :auth-visualisations (set/intersection (:auth-visualisations-set this) (set (:visualisation-ids ids)))
+   :auth-dashboards     (set/intersection (:auth-dashboards-set this) (set (:dashboard-ids ids)))
+   :auth-collections    (set/intersection (:auth-collections-set this) (set (:collections-ids ids)))})
+
 (defrecord AuthServiceImpl [auth-datasets-set auth-visualisations-set auth-dashboards-set auth-collections-set]
   p/AuthService2080
   (optimistic-allow? [this ids]
-    (set/subset? (set/union (:dataset-ids ids) (:visualisation-ids ids)
-                            (:dashboard-ids ids) (:collection-ids ids))
-                 (set/union auth-datasets-set auth-visualisations-set
-                            auth-dashboards-set auth-collections-set)))
+    (optimistic-allow?* this ids))
   p/AuthService
   (allow? [this ids]
-    (and (set/subset? (:visualisation-ids ids) auth-visualisations-set)
-         (set/subset? (:dataset-ids ids) auth-datasets-set)
-         (set/subset? (:dashboard-ids ids) auth-dashboards-set)
-         (set/subset? (:collection-ids ids) auth-collections-set)))
-
-  (auth [this {:keys [dataset-ids visualisation-ids dashboard-ids collections-ids]}]
-    {:auth-datasets       (set/intersection auth-datasets-set (set dataset-ids))
-     :auth-visualisations (set/intersection auth-visualisations-set (set visualisation-ids))
-     :auth-dashboards     (set/intersection auth-dashboards-set (set dashboard-ids))
-     :auth-collections    (set/intersection auth-collections-set (set collections-ids))})
-
+    (allow?* this ids))
+  (auth [this ids]
+    (auth* this ids))
   (auth [this type* uuid]
     (let [f* (fn [s u] (when (contains? s u) u))]
       (condp = type*


Make fx for browser notifications

Make fx for browser notifications

--- src/braid/core/client/core/events.cljs
+++ src/braid/core/client/core/events.cljs
@@ -1,6 +1,6 @@
 (ns braid.core.client.core.events
   (:require
-   [braid.core.hooks :as hooks]
+   [braid.core.client.desktop.notify :as notify]
    [braid.core.client.router :as router]
    [braid.core.client.routes :as routes]
    [braid.core.client.schema :as schema]
@@ -9,6 +9,7 @@
    [braid.core.client.sync :as sync]
    [braid.core.client.xhr :refer [edn-xhr]]
    [braid.core.common.util :as util]
+   [braid.core.hooks :as hooks]
    [clojure.set :as set]
    [clojure.string :as string]
    [re-frame.core :as re-frame :refer [dispatch reg-fx]]))
@@ -35,6 +36,8 @@
 (reg-fx :redirect-to (fn [route] (when route (router/go-to route))))

 (reg-fx :window-title (fn [title] (when title (set! (.-title js/document) title))))
+
+(reg-fx :notify notify/notify)

 (defn name->open-tag-id
   "Lookup tag by name in the open group"


[STORM-1245] port backtype.storm.daemon.acker to java

--- storm-core/src/clj/org/apache/storm/daemon/acker.clj
+++ storm-core/src/clj/org/apache/storm/daemon/acker.clj
@@ -20,7 +20,7 @@
   (:import [java.util List Map])
   (:import [org.apache.storm Constants]
            (org.apache.storm.daemon AckerBolt))
-  (:use [org.apache.storm config util log])
+  (:use [org.apache.storm config util])
   (:gen-class
     :init init
     :implements [org.apache.storm.task.IBolt]
@@ -35,7 +35,6 @@
 (defn mk-acker-bolt []
   (let [output-collector (MutableObject.)
         pending (MutableObject.)]
-    (log-message "Symbol AckerBolt"  (symbol "AckerBolt") )
     (AckerBolt.)))

 (defn -init []


If the onyx ZK root node is missing print message

and retry

--- src/clj/onyx_dashboard/http/server.clj
+++ src/clj/onyx_dashboard/http/server.clj
@@ -168,16 +168,21 @@
   (send-all-fn! [:deployment/listing deployments]))

 (defn refresh-deployments-watch [send-all-fn! zk-client]
-  (->> (zk/children zk-client zk-onyx/root-path :watcher (fn [_] (refresh-deployments-watch send-all-fn! zk-client)))
-       (map (juxt identity
-                  (partial zk-deployment-entry-stat zk-client)))
-       (map (fn [[child stat]]
-              (vector child
-                      {:created-at (java.util.Date. (:ctime stat))
-                       :modified-at (java.util.Date. (:mtime stat))})))
-       (into {})
-       (reset! deployments)
-       (distribute-deployments send-all-fn!)))
+  (if-let [children (zk/children zk-client zk-onyx/root-path :watcher (fn [_] (refresh-deployments-watch send-all-fn! zk-client)))]
+    (->> children
+         (map (juxt identity
+                    (partial zk-deployment-entry-stat zk-client)))
+         (map (fn [[child stat]]
+                (vector child
+                        {:created-at (java.util.Date. (:ctime stat))
+                         :modified-at (java.util.Date. (:mtime stat))})))
+         (into {})
+         (reset! deployments)
+         (distribute-deployments send-all-fn!))
+    (do
+      (println (format "Could not find deployments at %s. Retrying in 1s." zk-onyx/root-path))
+      (Thread/sleep 1000)
+      (recur send-all-fn! zk-client))))

 (defn event->uid [event]
   (get-in event [:ring-req :cookies "ring-session" :value]))


refactor

refactor

--- src/clj/salava/metabadge/metabadge.clj
+++ src/clj/salava/metabadge/metabadge.clj
@@ -3,16 +3,11 @@
             [salava.core.util :as u]
             [clojure.tools.logging :as log]
             [clojure.core.cache :as cache]
-            [clojure.string :refer [escape]]
             [slingshot.slingshot :refer :all]
             [pantomime.mime :refer [extension-for-name mime-type-of]]
             [clojure.core.reducers :as r]
             [salava.metabadge.db :as db]
             [clojure.string :as string]
-            [salava.badge.main :as b]
-            [salava.core.helper :refer [dump]]
-            [clojure.set :as s]
-            [medley.core :refer [distinct-by]]
             [yesql.core :refer [defqueries]]))

 (defqueries "sql/metabadge/queries.sql")
@@ -22,7 +17,7 @@
 (defonce metabadge-cache-storage (atom (-> {} (cache/lru-cache-factory :threshold 200) (cache/ttl-cache-factory :ttl (* (* 86400 1000) no-of-days-in-cache)))))

 (defn url? [s]
-  (not (clojure.string/blank? (re-find #"^http" (str s)))))
+  (not (string/blank? (re-find #"^http" (str s)))))

 (defn %completed [req gotten]
   (let [calc (Math/round (double (* (/ gotten req) 100)))]
@@ -173,7 +168,7 @@
 (defn is-metabadge? [ctx user_badge_id]
   (let [x (some-> (select-metabadge-info-from-user-badge {:id user_badge_id} (u/get-db ctx)) first)]
     (reduce-kv (fn [r k v]
-                 (assoc r k (if (clojure.string/blank? v) false true))) {} x)))
+                 (assoc r k (if (string/blank? v) false true))) {} x)))

 (defn is-received-metabadge? [ctx user_id metabadge_id]
   (let [check (select-user-received-metabadge-by-metabadge-id {:metabadge_id metabadge_id :user_id user_id} (u/get-db ctx))]


fix tick/cross on packages for no-fit scenario

--- src/cljs/ikea_clojure_cup/pack_it.cljs
+++ src/cljs/ikea_clojure_cup/pack_it.cljs
@@ -60,7 +60,7 @@
             (map-indexed
              (fn [idx {:keys [width height length pkg-id] :as package}]
                [:li {:key idx}
-                [bootstrap/glyph {:glyph (if (package-ids-missing pkg-id) :remove :ok)}]
+                [bootstrap/glyph {:glyph (if (or (= :no (:result result-state)) (package-ids-missing pkg-id)) :remove :ok)}]
                 (str " " width "cm x " height "cm x " length "cm")
                 [bootstrap/label name]])
              (mapcat :packages (-> @all-state :trolley :items))))]]


small fix

small fix

--- src/cljs/salava/badge/ui/evidence.cljs
+++ src/cljs/salava/badge/ui/evidence.cljs
@@ -358,7 +358,7 @@
                                                          (mo/open-modal [:page :view] {:page-id resource_id}))} url]
                                        (hyperlink url))
                               (hyperlink url))]
-                           (when-not (blank? name) [:div.inline [:label (t :badge/Name) ": "] name])
+                           (when-not (blank? name) [:div.inline.name [:label (t :badge/Name) ": "] name])
                            (when-not (blank? desc) [:div [:label (t :admin/Description) ": "]   desc])]

                           [:div [:button {:type "button"


Case should resolve to false if type unrecognised

--- src/kixi/datastore/transport_specs.clj
+++ src/kixi/datastore/transport_specs.clj
@@ -42,7 +42,7 @@
                               (= (:header meta)
                                  (::ms/header file-metadata))
                               (true? (::ms/header file-metadata)))
-                      true)))
+                      false)))
         :ret ::ms/file-metadata)

 (def key-mapping


woops, removed a space and broke mustache for a second;

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -54,7 +54,7 @@

     :plugins      [[lein-figwheel "0.5.16"]{{#test?}}
                    [lein-doo "0.1.8"]{{/test?}}]}
-   :prod {{{#10x?}}:dependencies [[day8.re-frame/tracing-stubs "0.5.1"]]{{/10x?}}}{{#handler?}}
+   :prod { {{#10x?}}:dependencies [[day8.re-frame/tracing-stubs "0.5.1"]]{{/10x?}}}{{#handler?}}
    :uberjar {:source-paths ["env/prod/clj"]{{#10x?}}
              :dependencies [[day8.re-frame/tracing-stubs "0.5.1"]]{{/10x?}}
              :omit-source  true


Upgrade compojure to 1.6.2

Upgrade compojure to 1.6.2

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -12,7 +12,7 @@
                  [clj-commons/secretary "1.2.4"]{{/routes?}}{{#garden?}}
                  [garden "1.3.10"]
                  [ns-tracker "0.4.0"]{{/garden?}}{{#handler?}}
-                 [compojure "1.6.1"]
+                 [compojure "1.6.2"]
                  [yogthos/config "1.1.7"]
                  [ring "1.8.1"]{{/handler?}}{{#re-pressed?}}
                  [re-pressed "0.3.1"]{{/re-pressed?}}{{#breaking-point?}}


Benchmark against httprouter, reitit is ~3-6x slower

--- perf-test/clj/reitit/go_perf_test.clj
+++ perf-test/clj/reitit/go_perf_test.clj
@@ -2,7 +2,8 @@
   (:require [criterium.core :as cc]
             [reitit.perf-utils :refer :all]
             [reitit.ring :as ring]
-            [clojure.string :as str]))
+            [clojure.string :as str]
+            [reitit.core :as r]))

 ;;
 ;; start repl with `lein perf repl`
@@ -31,46 +32,266 @@
       (mapv (fn [[p d]] (if (= path p) [p (assoc d method h)] [p d])) routes)
       (conj routes [path {method h}]))))

-(def routes [{"POST", "/1/classes/:className"},
-             {"GET", "/1/classes/:className/:objectId"},
-             {"PUT", "/1/classes/:className/:objectId"},
-             {"GET", "/1/classes/:className"},
-             {"DELETE", "/1/classes/:className/:objectId"},
-
-             ;; Users
-             {"POST", "/1/users"},
-             {"GET", "/1/login"},
-             {"GET", "/1/users/:objectId"},
-             {"PUT", "/1/users/:objectId"},
-             {"GET", "/1/users"},
-             {"DELETE", "/1/users/:objectId"},
-             {"POST", "/1/requestPasswordReset"},
-
-             ;; Roles
-             {"POST", "/1/roles"},
-             {"GET", "/1/roles/:objectId"},
-             {"PUT", "/1/roles/:objectId"},
-             {"GET", "/1/roles"},
-             {"DELETE", "/1/roles/:objectId"},
-
-             ;; Files
-             {"POST", "/1/files/:fileName"},
-
-             ;; Analytics
-             {"POST", "/1/events/:eventName"},
-
-             ;; Push Notifications
-             {"POST", "/1/push"},
-
-             ;; Installations
-             {"POST", "/1/installations"},
-             {"GET", "/1/installations/:objectId"},
-             {"PUT", "/1/installations/:objectId"},
-             {"GET", "/1/installations"},
-             {"DELETE", "/1/installations/:objectId"},
-
-             ;; Cloud Functions
-             {"POST", "/1/functions"}])
+(def routes
+  [{"GET" "/authorizations"}
+   {"GET" "/authorizations/:id"}
+   {"POST" "/authorizations"}
+   ;; {"PUT" "/authorizations/clients/:client_id"}
+   ;; {"PATCH" "/authorizations/:id"}
+   {"DELETE" "/authorizations/:id"}
+   {"GET" "/applications/:client_id/tokens/:access_token"}
+   {"DELETE" "/applications/:client_id/tokens"}
+   {"DELETE" "/applications/:client_id/tokens/:access_token"}
+
+   ;; Activity
+   {"GET" "/events"}
+   {"GET" "/repos/:owner/:repo/events"}
+   {"GET" "/networks/:owner/:repo/events"}
+   {"GET" "/orgs/:org/events"}
+   {"GET" "/users/:user/received_events"}
+   {"GET" "/users/:user/received_events/public"}
+   {"GET" "/users/:user/events"}
+   {"GET" "/users/:user/events/public"}
+   {"GET" "/users/:user/events/orgs/:org"}
+   {"GET" "/feeds"}
+   {"GET" "/notifications"}
+   {"GET" "/repos/:owner/:repo/notifications"}
+   {"PUT" "/notifications"}
+   {"PUT" "/repos/:owner/:repo/notifications"}
+   {"GET" "/notifications/threads/:id"}
+   ;; {"PATCH" "/notifications/threads/:id"}
+   {"GET" "/notifications/threads/:id/subscription"}
+   {"PUT" "/notifications/threads/:id/subscription"}
+   {"DELETE" "/notifications/threads/:id/subscription"}
+   {"GET" "/repos/:owner/:repo/stargazers"}
+   {"GET" "/users/:user/starred"}
+   {"GET" "/user/starred"}
+   {"GET" "/user/starred/:owner/:repo"}
+   {"PUT" "/user/starred/:owner/:repo"}
+   {"DELETE" "/user/starred/:owner/:repo"}
+   {"GET" "/repos/:owner/:repo/subscribers"}
+   {"GET" "/users/:user/subscriptions"}
+   {"GET" "/user/subscriptions"}
+   {"GET" "/repos/:owner/:repo/subscription"}
+   {"PUT" "/repos/:owner/:repo/subscription"}
+   {"DELETE" "/repos/:owner/:repo/subscription"}
+   {"GET" "/user/subscriptions/:owner/:repo"}
+   {"PUT" "/user/subscriptions/:owner/:repo"}
+   {"DELETE" "/user/subscriptions/:owner/:repo"}
+
+   ;; Gists
+   {"GET" "/users/:user/gists"}
+   {"GET" "/gists"}
+   ;; {"GET" "/gists/public"}
+   ;; {"GET" "/gists/starred"}
+   {"GET" "/gists/:id"}
+   {"POST" "/gists"}
+   ;; {"PATCH" "/gists/:id"}
+   {"PUT" "/gists/:id/star"}
+   {"DELETE" "/gists/:id/star"}
+   {"GET" "/gists/:id/star"}
+   {"POST" "/gists/:id/forks"}
+   {"DELETE" "/gists/:id"}
+
+   ;; Git Data
+   {"GET" "/repos/:owner/:repo/git/blobs/:sha"}
+   {"POST" "/repos/:owner/:repo/git/blobs"}
+   {"GET" "/repos/:owner/:repo/git/commits/:sha"}
+   {"POST" "/repos/:owner/:repo/git/commits"}
+   ;; {"GET" "/repos/:owner/:repo/git/refs/*ref"}
+   {"GET" "/repos/:owner/:repo/git/refs"}
+   {"POST" "/repos/:owner/:repo/git/refs"}
+   ;; {"PATCH" "/repos/:owner/:repo/git/refs/*ref"}
+   ;; {"DELETE" "/repos/:owner/:repo/git/refs/*ref"}
+   {"GET" "/repos/:owner/:repo/git/tags/:sha"}
+   {"POST" "/repos/:owner/:repo/git/tags"}
+   {"GET" "/repos/:owner/:repo/git/trees/:sha"}
+   {"POST" "/repos/:owner/:repo/git/trees"}
+
+   ;; Issues
+   {"GET" "/issues"}
+   {"GET" "/user/issues"}
+   {"GET" "/orgs/:org/issues"}
+   {"GET" "/repos/:owner/:repo/issues"}
+   {"GET" "/repos/:owner/:repo/issues/:number"}
+   {"POST" "/repos/:owner/:repo/issues"}
+   ;; {"PATCH" "/repos/:owner/:repo/issues/:number"}
+   {"GET" "/repos/:owner/:repo/assignees"}
+   {"GET" "/repos/:owner/:repo/assignees/:assignee"}
+   {"GET" "/repos/:owner/:repo/issues/:number/comments"}
+   ;; {"GET" "/repos/:owner/:repo/issues/comments"}
+   ;; {"GET" "/repos/:owner/:repo/issues/comments/:id"}
+   {"POST" "/repos/:owner/:repo/issues/:number/comments"}
+   ;; {"PATCH" "/repos/:owner/:repo/issues/comments/:id"}
+   ;; {"DELETE" "/repos/:owner/:repo/issues/comments/:id"}
+   {"GET" "/repos/:owner/:repo/issues/:number/events"}
+   ;; {"GET" "/repos/:owner/:repo/issues/events"}
+   ;; {"GET" "/repos/:owner/:repo/issues/events/:id"}
+   {"GET" "/repos/:owner/:repo/labels"}
+   {"GET" "/repos/:owner/:repo/labels/:name"}
+   {"POST" "/repos/:owner/:repo/labels"}
+   ;; {"PATCH" "/repos/:owner/:repo/labels/:name"}
+   {"DELETE" "/repos/:owner/:repo/labels/:name"}
+   {"GET" "/repos/:owner/:repo/issues/:number/labels"}
+   {"POST" "/repos/:owner/:repo/issues/:number/labels"}
+   {"DELETE" "/repos/:owner/:repo/issues/:number/labels/:name"}
+   {"PUT" "/repos/:owner/:repo/issues/:number/labels"}
+   {"DELETE" "/repos/:owner/:repo/issues/:number/labels"}
+   {"GET" "/repos/:owner/:repo/milestones/:number/labels"}
+   {"GET" "/repos/:owner/:repo/milestones"}
+   {"GET" "/repos/:owner/:repo/milestones/:number"}
+   {"POST" "/repos/:owner/:repo/milestones"}
+   ;; {"PATCH" "/repos/:owner/:repo/milestones/:number"}
+   {"DELETE" "/repos/:owner/:repo/milestones/:number"}
+
+   ;; Miscellaneous
+   {"GET" "/emojis"}
+   {"GET" "/gitignore/templates"}
+   {"GET" "/gitignore/templates/:name"}
+   {"POST" "/markdown"}
+   {"POST" "/markdown/raw"}
+   {"GET" "/meta"}
+   {"GET" "/rate_limit"}
+
+   ;; Organizations
+   {"GET" "/users/:user/orgs"}
+   {"GET" "/user/orgs"}
+   {"GET" "/orgs/:org"}
+   ;; {"PATCH" "/orgs/:org"}
+   {"GET" "/orgs/:org/members"}
+   {"GET" "/orgs/:org/members/:user"}
+   {"DELETE" "/orgs/:org/members/:user"}
+   {"GET" "/orgs/:org/public_members"}
+   {"GET" "/orgs/:org/public_members/:user"}
+   {"PUT" "/orgs/:org/public_members/:user"}
+   {"DELETE" "/orgs/:org/public_members/:user"}
+   {"GET" "/orgs/:org/teams"}
+   {"GET" "/teams/:id"}
+   {"POST" "/orgs/:org/teams"}
+   ;; {"PATCH" "/teams/:id"}
+   {"DELETE" "/teams/:id"}
+   {"GET" "/teams/:id/members"}
+   {"GET" "/teams/:id/members/:user"}
+   {"PUT" "/teams/:id/members/:user"}
+   {"DELETE" "/teams/:id/members/:user"}
+   {"GET" "/teams/:id/repos"}
+   {"GET" "/teams/:id/repos/:owner/:repo"}
+   {"PUT" "/teams/:id/repos/:owner/:repo"}
+   {"DELETE" "/teams/:id/repos/:owner/:repo"}
+   {"GET" "/user/teams"}
+
+   ;; Pull Requests
+   {"GET" "/repos/:owner/:repo/pulls"}
+   {"GET" "/repos/:owner/:repo/pulls/:number"}
+   {"POST" "/repos/:owner/:repo/pulls"}
+   ;; {"PATCH" "/repos/:owner/:repo/pulls/:number"}
+   {"GET" "/repos/:owner/:repo/pulls/:number/commits"}
+   {"GET" "/repos/:owner/:repo/pulls/:number/files"}
+   {"GET" "/repos/:owner/:repo/pulls/:number/merge"}
+   {"PUT" "/repos/:owner/:repo/pulls/:number/merge"}
+   {"GET" "/repos/:owner/:repo/pulls/:number/comments"}
+   ;; {"GET" "/repos/:owner/:repo/pulls/comments"}
+   ;; {"GET" "/repos/:owner/:repo/pulls/comments/:number"}
+   {"PUT" "/repos/:owner/:repo/pulls/:number/comments"}
+   ;; {"PATCH" "/repos/:owner/:repo/pulls/comments/:number"}
+   ;; {"DELETE" "/repos/:owner/:repo/pulls/comments/:number"}
+
+   ;; Repositories
+   {"GET" "/user/repos"}
+   {"GET" "/users/:user/repos"}
+   {"GET" "/orgs/:org/repos"}
+   {"GET" "/repositories"}
+   {"POST" "/user/repos"}
+   {"POST" "/orgs/:org/repos"}
+   {"GET" "/repos/:owner/:repo"}
+   ;; {"PATCH" "/repos/:owner/:repo"}
+   {"GET" "/repos/:owner/:repo/contributors"}
+   {"GET" "/repos/:owner/:repo/languages"}
+   {"GET" "/repos/:owner/:repo/teams"}
+   {"GET" "/repos/:owner/:repo/tags"}
+   {"GET" "/repos/:owner/:repo/branches"}
+   {"GET" "/repos/:owner/:repo/branches/:branch"}
+   {"DELETE" "/repos/:owner/:repo"}
+   {"GET" "/repos/:owner/:repo/collaborators"}
+   {"GET" "/repos/:owner/:repo/collaborators/:user"}
+   {"PUT" "/repos/:owner/:repo/collaborators/:user"}
+   {"DELETE" "/repos/:owner/:repo/collaborators/:user"}
+   {"GET" "/repos/:owner/:repo/comments"}
+   {"GET" "/repos/:owner/:repo/commits/:sha/comments"}
+   {"POST" "/repos/:owner/:repo/commits/:sha/comments"}
+   {"GET" "/repos/:owner/:repo/comments/:id"}
+   ;; {"PATCH" "/repos/:owner/:repo/comments/:id"}
+   {"DELETE" "/repos/:owner/:repo/comments/:id"}
+   {"GET" "/repos/:owner/:repo/commits"}
+   {"GET" "/repos/:owner/:repo/commits/:sha"}
+   {"GET" "/repos/:owner/:repo/readme"}
+   ;; {"GET" "/repos/:owner/:repo/contents/*path"}
+   ;; {"PUT" "/repos/:owner/:repo/contents/*path"}
+   ;; {"DELETE" "/repos/:owner/:repo/contents/*path"}
+   ;; {"GET" "/repos/:owner/:repo/:archive_format/:ref"}
+   {"GET" "/repos/:owner/:repo/keys"}
+   {"GET" "/repos/:owner/:repo/keys/:id"}
+   {"POST" "/repos/:owner/:repo/keys"}
+   ;; {"PATCH" "/repos/:owner/:repo/keys/:id"}
+   {"DELETE" "/repos/:owner/:repo/keys/:id"}
+   {"GET" "/repos/:owner/:repo/downloads"}
+   {"GET" "/repos/:owner/:repo/downloads/:id"}
+   {"DELETE" "/repos/:owner/:repo/downloads/:id"}
+   {"GET" "/repos/:owner/:repo/forks"}
+   {"POST" "/repos/:owner/:repo/forks"}
+   {"GET" "/repos/:owner/:repo/hooks"}
+   {"GET" "/repos/:owner/:repo/hooks/:id"}
+   {"POST" "/repos/:owner/:repo/hooks"}
+   ;; {"PATCH" "/repos/:owner/:repo/hooks/:id"}
+   {"POST" "/repos/:owner/:repo/hooks/:id/tests"}
+   {"DELETE" "/repos/:owner/:repo/hooks/:id"}
+   {"POST" "/repos/:owner/:repo/merges"}
+   {"GET" "/repos/:owner/:repo/releases"}
+   {"GET" "/repos/:owner/:repo/releases/:id"}
+   {"POST" "/repos/:owner/:repo/releases"}
+   ;; {"PATCH" "/repos/:owner/:repo/releases/:id"}
+   {"DELETE" "/repos/:owner/:repo/releases/:id"}
+   {"GET" "/repos/:owner/:repo/releases/:id/assets"}
+   {"GET" "/repos/:owner/:repo/stats/contributors"}
+   {"GET" "/repos/:owner/:repo/stats/commit_activity"}
+   {"GET" "/repos/:owner/:repo/stats/code_frequency"}
+   {"GET" "/repos/:owner/:repo/stats/participation"}
+   {"GET" "/repos/:owner/:repo/stats/punch_card"}
+   {"GET" "/repos/:owner/:repo/statuses/:ref"}
+   {"POST" "/repos/:owner/:repo/statuses/:ref"}
+
+   ;; Search
+   {"GET" "/search/repositories"}
+   {"GET" "/search/code"}
+   {"GET" "/search/issues"}
+   {"GET" "/search/users"}
+   {"GET" "/legacy/issues/search/:owner/:repository/:state/:keyword"}
+   {"GET" "/legacy/repos/search/:keyword"}
+   {"GET" "/legacy/user/search/:keyword"}
+   {"GET" "/legacy/user/email/:email"}
+
+   ;; Users
+   {"GET" "/users/:user"}
+   {"GET" "/user"}
+   ;; {"PATCH" "/user"}
+   {"GET" "/users"}
+   {"GET" "/user/emails"}
+   {"POST" "/user/emails"}
+   {"DELETE" "/user/emails"}
+   {"GET" "/users/:user/followers"}
+   {"GET" "/user/followers"}
+   {"GET" "/users/:user/following"}
+   {"GET" "/user/following"}
+   {"GET" "/user/following/:user"}
+   {"GET" "/users/:user/following/:target_user"}
+   {"PUT" "/user/following/:user"}
+   {"DELETE" "/user/following/:user"}
+   {"GET" "/users/:user/keys"}
+   {"GET" "/user/keys"}
+   {"GET" "/user/keys/:id"}
+   {"POST" "/user/keys"}
+   ;; {"PATCH" "/user/keys/:id"}
+   {"DELETE" "/user/keys/:id"}])

 (def app
@@ -78,33 +299,39 @@
     (ring/router
       (reduce (partial add h) [] routes))))

+(defrecord Req [uri request-method])
+
+(defn route->req [route]
+  (map->Req {:request-method (-> route keys first str/lower-case keyword)
+             :uri (str/replace (-> route vals first) #"\/:\w+" "/1")}))
+
 (defn routing-test []
   ;; https://github.com/julienschmidt/go-http-routing-benchmark
-  ;; coudn't run the GO tests, so reusing just the numbers (run on better hw?):
-  ;;
-  ;; Intel Core i5-2500K (4x 3,30GHz + Turbo Boost), CPU-governor: performance
-  ;; 2x 4 GiB DDR3-1333 RAM, dual-channel
-  ;; go version go1.3rc1 linux/amd64
-  ;; Ubuntu 14.04 amd64 (Linux Kernel 3.13.0-29), fresh installation
-
-  ;;  37ns (2.0x)
-  ;; 180ns (4.0x)
-  ;; 200ns (4.8x)
-  "httpRouter"
-
-  ;;  77ns -> 120ns (decode path-params)
-  ;; 700ns -> 795ns (decode path-params)
-  ;; 890ns -> 1000ns (decode path-params)
-  (title "reitit-ring")
-  (let [r1 (map->Request {:request-method :get, :uri "/1/users"})
-        r2 (map->Request {:request-method :get, :uri "/1/classes/go"})
-        r3 (map->Request {:request-method :get, :uri "/1/classes/go/123456789"})]
-    (assert (= {:status 200, :body "/1/users"} (app r1)))
-    (assert (= {:status 200, :body "/1/classes/:className"} (app r2)))
-    (assert (= {:status 200, :body "/1/classes/:className/:objectId"} (app r3)))
-    (cc/quick-bench (app r1))
-    (cc/quick-bench (app r2))
-    (cc/quick-bench (app r3))))
+  ;; go test -bench="HttpRouter"
+
+  (suite "httprouter vs reitit-ring")
+
+  ;;  40ns (httprouter)
+  ;; 140ns
+  (let [req (map->Req {:request-method :get, :uri "/user/repos"})]
+      (title "static")
+      (assert (= {:status 200, :body "/user/repos"} (app req)))
+      (cc/quick-bench (app req)))
+
+  ;; 160ns (httprouter)
+  ;; 990ns
+  (let [req (map->Req {:request-method :get, :uri "/repos/julienschmidt/httprouter/stargazers"})]
+      (title "param")
+      (assert (= {:status 200, :body "/repos/:owner/:repo/stargazers"} (app req)))
+      (cc/quick-bench (app req)))
+
+  ;;  30µs (httprouter)
+  ;; 190µs
+  (let [requests (mapv route->req routes)]
+    (title "all")
+    (cc/quick-bench
+      (doseq [r requests]
+        (app r)))))

 (comment
   (routing-test))


CLJS-1306: Browser REPL :asset-path with leading slash breaks source map support

`cljs.repl.browser/parse-file` removes the base url including the trailing slash as we
need relative paths. However `:asset-path` may have a leading slash
(i.e. "/js" or "/assets/js"). If a leading slash is specified just strip it.

--- src/main/clojure/cljs/repl/browser.clj
+++ src/main/clojure/cljs/repl/browser.clj
@@ -227,14 +227,20 @@
        (cond-> column
          (.endsWith column ")") (string/replace ")" "")))]))

-(defn parse-file [{:keys [host host-port port] :as repl-env} file {:keys [asset-path] :as opts}]
+(defn parse-file
+  "Given a browser file url convert it into a relative path that can be used
+   to locate the original source."
+  [{:keys [host host-port port] :as repl-env} file {:keys [asset-path] :as opts}]
   (let [base-url-pattern (Pattern/compile (str "http://" host ":" (or host-port port) "/"))]
     (if (re-find base-url-pattern file)
       (-> file
         (string/replace base-url-pattern "")
         (string/replace
           (Pattern/compile
-            (str "^" (or asset-path (util/output-directory opts)) "/")) ""))
+            ;; if :asset-path specified drop leading slash
+            (str "^" (or (and asset-path (string/replace asset-path #"^/" ""))
+                         (util/output-directory opts)) "/"))
+          ""))
       (if-let [asset-root (:asset-root opts)]
         (string/replace file asset-root "")
         (throw
@@ -295,6 +301,21 @@
     at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (http://localhost:9000/out/cljs/core.js:28706:14)"
     {:ua-product :chrome}
     nil)
+
+  (parse-stacktrace {:host "localhost" :port 9000}
+    "Error: 1 is not ISeqable
+    at Object.cljs$core$seq [as seq] (http://localhost:9000/js/cljs/core.js:4258:8)
+    at Object.cljs$core$first [as first] (http://localhost:9000/js/cljs/core.js:4288:19)
+    at cljs$core$ffirst (http://localhost:9000/js/cljs/core.js:5356:34)
+    at http://localhost:9000/js/cljs/core.js:16971:89
+    at cljs.core.map.cljs$core$map__2 (http://localhost:9000/js/cljs/core.js:16972:3)
+    at http://localhost:9000/js/cljs/core.js:10981:129
+    at cljs.core.LazySeq.sval (http://localhost:9000/js/cljs/core.js:10982:3)
+    at cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1 (http://localhost:9000/js/cljs/core.js:11073:10)
+    at Object.cljs$core$seq [as seq] (http://localhost:9000/js/cljs/core.js:4239:13)
+    at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (http://localhost:9000/js/cljs/core.js:28706:14)"
+    {:ua-product :chrome}
+    {:asset-path "/js"})

   (parse-stacktrace {:host "localhost" :port 9000}
     "Error: 1 is not ISeqable
@@ -447,7 +468,7 @@
     vec))

 (comment
-  (parse-stacktrace nil
+  (parse-stacktrace {:host "localhost" :port 9000}
     "cljs$core$seq@http://localhost:9000/out/cljs/core.js:4258:8
 cljs$core$first@http://localhost:9000/out/cljs/core.js:4288:9
 cljs$core$ffirst@http://localhost:9000/out/cljs/core.js:5356:24


Replaced defn ^:private with defn- so it will build on Clojure 1.2

--- src/main/clojure/clojure/tools/cli.clj
+++ src/main/clojure/clojure/tools/cli.clj
@@ -4,12 +4,12 @@
         [clojure.pprint :only (pprint cl-format)])
   (:refer-clojure :exclude [replace]))

-(defn ^:private build-doc [{:keys [switches docs default]}]
+(defn- build-doc [{:keys [switches docs default]}]
   [(apply str (interpose ", " switches))
    (or (str default) "")
    (or docs "")])

-(defn ^:private banner-for [specs]
+(defn- banner-for [specs]
   (println "Usage:")
   (println)
   (let [docs (into (map build-doc specs)
@@ -24,22 +24,22 @@
       (cl-format true "~{ ~vA  ~vA  ~vA ~}" v)
       (prn))))

-(defn ^:private name-for [k]
+(defn- name-for [k]
   (replace k #"^--no-|^--\[no-\]|^--|^-" ""))

-(defn ^:private flag-for [^String v]
+(defn- flag-for [^String v]
   (not (.startsWith v "--no-")))

-(defn ^:private opt? [^String x]
+(defn- opt? [^String x]
   (.startsWith x "-"))

-(defn ^:private flag? [^String x]
+(defn- flag? [^String x]
   (.startsWith x "--[no-]"))

-(defn ^:private end-of-args? [x]
+(defn- end-of-args? [x]
   (= "--" x))

-(defn ^:private spec-for
+(defn- spec-for
   [arg specs]
   (->> specs
        (filter (fn [s]
@@ -47,11 +47,11 @@
                      (contains? switches arg))))
        first))

-(defn ^:private default-values-for
+(defn- default-values-for
   [specs]
   (into {} (for [s specs] [(s :name) (s :default)])))

-(defn ^:private apply-specs
+(defn- apply-specs
   [specs args]
   (loop [options    (default-values-for specs)
          extra-args []
@@ -80,7 +80,7 @@
          :default
          (recur options (conj extra-args (first args)) (rest args)))))))

-(defn ^:private switches-for
+(defn- switches-for
   [switches flag]
   (-> (for [^String s switches]
         (cond
@@ -89,7 +89,7 @@
          :default                        [s]))
       flatten))

-(defn ^:private generate-spec
+(defn- generate-spec
   [raw-spec]
   (let [[switches raw-spec] (split-with #(and (string? %) (opt? %)) raw-spec)
         [docs raw-spec]     (split-with string? raw-spec)


Convert date into iso date

Convert date into iso date

--- raw_data/convert_players.clj
+++ raw_data/convert_players.clj
@@ -11,6 +11,10 @@
         word-names (map capitalize words)]
     (join " " word-names)))

+(defn iso-date [s]
+  (let [[day month year] (split s #"/")]
+    (format "%s-%s-%s" year month day)))
+
 (defn convert-player [country data]
   (let [shirt (data 0)]
     {
@@ -18,7 +22,7 @@
       :country (nameify country)
       :name (nameify (data 1))
       :shirt_number shirt
-      :date_of_birth (data 2)
+      :date_of_birth (iso-date (data 2))
       :position (data 3)
       :club (data 4)
       :height (data 5)


Doc-strings are no longer ignored, but are instead reported.

--- examples/basic/test/basic/core_test.clj
+++ examples/basic/test/basic/core_test.clj
@@ -1,4 +1,3 @@
-
 (ns basic.core-test
   (:use clojure.test)
   (:use midje.sweet)
@@ -24,7 +23,7 @@
  (+ 1 1) => 2
  (+ 1 0) => 1)

-;; Notice also that you can add "doc strings" to facts. Right now, they're just ignored.
+;; Notice also that you can add "doc strings" to facts.

 ;; Failing tests should look familiar:
 ;;     FAIL at (core_test.clj:34)


fix comment argvec order

fix comment argvec order

--- src/open_company/resources/company.clj
+++ src/open_company/resources/company.clj
@@ -147,16 +147,16 @@
         (sections-for))))

 (s/defn add-updated-at
-  [{:keys [section-name] :as section} :- common/Section ts]
   "Add `:updated-at` key with `ts` as value to a given section.
    If the sectino has a `:notes` key also add the timestamp there."
+  [{:keys [section-name] :as section} :- common/Section ts]
   (let [notes-section? (contains? common/notes-sections section-name)]
     (cond-> (assoc section :updated-at ts)
       (and notes-section? (:notes section)) (assoc-in [:notes :updated-at] ts))))

 (s/defn create-company!
+  "Create a company document in RethinkDB. Add `updated-at` keys where necessary."
   [company :- common/Company]
-  "Create a company document in RethinkDB. Add `updated-at` keys where necessary."
   (s/validate common/Company company) ; throw if invalid
   (let [real-sections (real-sections company)
         ts (common/current-timestamp)


Working support for storeTimeEnd/Start params.

--- src/ruuvi_server/database/entities.clj
+++ src/ruuvi_server/database/entities.clj
@@ -2,6 +2,7 @@
   (:use korma.db)
   (:use korma.core)
   (:use [clojure.tools.logging :only (debug info warn error)])
+  (:require [ruuvi-server.util :as util])
   (:import org.joda.time.DateTime)
   )

@@ -54,9 +55,6 @@
   (defn- current-sql-timestamp []
     (to-sql-timestamp (org.joda.time.DateTime)))

-  (defn- remove-nil-values [map-data]
-    (flatten (filter (fn [x] (nth x 1) ) map-data) ))
-
   ;; public functions
   (defn get-trackers [ids]
     (select tracker
@@ -120,27 +118,23 @@
           max-results (:maxResults criteria max-result-count)
           result-limit (min max-result-count max-results)

-          ;; TODO ugly hack around Korma macro thing: one condition clause may not hold several references to single field
-          conditions1 (merge
-                       (when event-start {:event_time ['>= event-start] })
-                       (when store-start {:created_on ['>= store-start] })
-                       (when tracker-ids {:tracker_id ['in tracker-ids] }))
-          conditions2 (merge
-                       (when event-end {:event_time ['<= event-end] })
-                       (when store-end {:created_on ['<= store-end] }))
+          tracker-ids-crit (when tracker-ids {:tracker_id ['in tracker-ids]})
+          event-start-crit (when event-start {:event_time ['>= event-start]})
+          event-end-crit (when event-end {:event_time ['<= event-end]})
+          store-start-crit (when store-start {:created_on ['>= store-start]})
+          store-end-crit (when store-end {:created_on ['<= store-end]})
+          conditions (filter identity (list event-start-crit event-end-crit tracker-ids-crit))
           ]
-      (if (not (and (empty? conditions1) (empty? conditions2)))
+      (if (not (empty? conditions))
         (let [results (select event
                               (with event-location)
                               (with event-extension-value (fields :value)
                                     (with event-extension-type (fields :name)))
-                              (where (and (and conditions1) conditions2))
-                              (limit result-limit))
-                              ]
-
+                              (where (apply and conditions))
+                              (limit result-limit)) ]
           results
           )
-        '())))
+        '() )))

   (defn get-events [ids]
     (select event
@@ -160,7 +154,7 @@
     )

   (defn get-tracker [id]
-    ;; TODO support also fetching with tracker_indentifier
+    ;; TODO support also fetching with tracker_indentifier?
     (first (select tracker
                    (where {:id id}))))


Revert "Use wmflabs as the toolserver is down."

This reverts commit 15400c2671bd985cc53c505198136b400b2efcc9.

--- src/wlmmap/vars.clj
+++ src/wlmmap/vars.clj
@@ -86,11 +86,11 @@
    })

 (def toolserver-url
-  ;; "http://toolserver.org/~erfgoed/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article")
-  "http://tools.wmflabs.org/heritage/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article")
+  "http://toolserver.org/~erfgoed/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article")
+;;  "http://tools.wmflabs.org/heritage/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article")
 (def toolserver-bbox-format-url
-  "http://tools.wmflabs.org/heritage/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article&bbox=%s")
-;; "http://toolserver.org/~erfgoed/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article&bbox=%s")
+;;  "http://tools.wmflabs.org/heritage/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article&bbox=%s")
+  "http://toolserver.org/~erfgoed/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article&bbox=%s")
 (def wm-thumbnail-format-url
   "<img src=\"https://commons.wikimedia.org/w/index.php?title=Special%%3AFilePath&file=%s&width=250\" />")
 (def wm-img-format-url


fix: deserialize custom bootnodes settings correctly

Signed-off-by: yenda <96f164ad4d9b2b0dacf8ebee2bb1eeb3aa69adf1@status.im>

--- src/status_im/data_store/settings.cljs
+++ src/status_im/data_store/settings.cljs
@@ -21,7 +21,7 @@

 (defn rpc->custom-bootnodes [custom-bootnodes]
   (reduce-kv (fn [acc chain custom-bootnodes]
-               (assoc acc (str chain) custom-bootnodes))
+               (assoc acc (name chain) custom-bootnodes))
              {}
              custom-bootnodes))

@@ -39,4 +39,6 @@
       (update :wallet/visible-tokens rpc->visible-tokens)
       (update :pinned-mailservers rpc->pinned-mailservers)
       (update :stickers/packs-installed rpc->stickers-packs)
+      (update :custom-bootnodes rpc->custom-bootnodes)
+      (update :custom-bootnodes-enabled? rpc->custom-bootnodes)
       (update :currency keyword)))


Message queue: use `lua-message-status` in `dequeue` (easier to maintain)

--- src/taoensso/carmine/message_queue.clj
+++ src/taoensso/carmine/message_queue.clj
@@ -70,38 +70,46 @@

 ;;;; Implementation

-(def ^:private lua-message-status
-  ;; Careful, logic here's quite subtle: see state diagram for assistance
-  "--
-   local now         = tonumber(_:now)
-   local lock_exp    = tonumber(redis.call('hget', _:qk-locks,    _:mid) or 0)
-   local backoff_exp = tonumber(redis.call('hget', _:qk-backoffs, _:mid) or 0)
-   local state       = nil
-   if redis.call('hexists', _:qk-messages, _:mid) == 1 then
-     if redis.call('sismember', _:qk-done, _:mid) == 1 then
-       if (now < backoff_exp) then
-         if redis.call('sismember', _:qk-requeue, _:mid) == 1 then
-           state = 'done-with-requeue'
+(def ^:private script-with-msg-status
+  (memoize
+   (fn [mid-arg? preamble conclusion]
+     (format "%s\n%s\n%s"
+      (or preamble "")
+      (str (when mid-arg? "local mid = _:mid\n")
+       ;; Careful, logic here's quite subtle: see state diagram for assistance
+       "--
+       local now         = tonumber(_:now)
+       local lock_exp    = tonumber(redis.call('hget', _:qk-locks,    mid) or 0)
+       local backoff_exp = tonumber(redis.call('hget', _:qk-backoffs, mid) or 0)
+       local state       = nil
+       if redis.call('hexists', _:qk-messages, mid) == 1 then
+         if redis.call('sismember', _:qk-done, mid) == 1 then
+           if (now < backoff_exp) then
+             if redis.call('sismember', _:qk-requeue, mid) == 1 then
+               state = 'done-with-requeue'
+             else
+               state = 'done-with-backoff'
+             end
+           else
+             state = 'done-awaiting-gc'
+           end
          else
-           state = 'done-with-backoff'
+           if (now < lock_exp) then
+             if redis.call('sismember', _:qk-requeue, mid) == 1 then
+               state = 'locked-with-requeue'
+             else
+               state = 'locked'
+             end
+             elseif (now < backoff_exp) then
+             state = 'queued-with-backoff'
+           else
+             state = 'queued'
+           end
          end
-       else
-         state = 'done-awaiting-gc'
-       end
-     else
-       if (now < lock_exp) then
-         if redis.call('sismember', _:qk-requeue, _:mid) == 1 then
-           state = 'locked-with-requeue'
-         else
-           state = 'locked'
-         end
-       elseif (now < backoff_exp) then
-         state = 'queued-with-backoff'
-       else
-         state = 'queued'
-       end
-     end
-   end")
+       end")
+      conclusion))))
+
+(comment (script-with-msg-status :mid-arg "preamble" "conclusion"))

 (defn message-status
   "Returns current message status, e/o:
@@ -114,8 +122,8 @@
     nil                   - Already GC'd or invalid message id."
   [qname mid]
   (car/parse-keyword
-   (car/lua ; Careful, logic here's quite subtle: see state diagram for assistance
-    (format "%s\n%s" lua-message-status "return state")
+   (car/lua
+    (script-with-msg-status :mid-arg nil "return state")
     {:qk-messages (qkey qname :messages)
      :qk-locks    (qkey qname :locks)
      :qk-backoffs (qkey qname :backoffs)
@@ -137,7 +145,7 @@
   [qname message & [unique-message-id allow-requeue?]]
   (->>
    (car/lua
-    (format "%s\n%s" lua-message-status
+    (script-with-msg-status :mid-arg nil
      "--
      if (_:allow-requeue? == 'true') and
         ((state == 'locked') or (state == 'done-with-backoff')) and
@@ -196,48 +204,51 @@
               (integer? eoq-backoff-ms) (mapv (constantly eoq-backoff-ms) (range 5))
               :else (throw (Exception. (str "Bad eoq-backoff-ms: " eoq-backoff-ms))))]
     (car/lua
-     "if redis.call('exists', _:qk-eoq-backoff) == 1 then return 'eoq-backoff' end
-
-     -- TODO Waiting for Lua brpoplpush support to get us long polling
-     local mid = redis.call('rpoplpush', _:qk-mid-circle, _:qk-mid-circle)
-     local now = tonumber(_:now)
-
-     if (not mid) or (mid == 'end-of-circle') then -- Uninit'd or eoq
-
-       -- Calculate eoq_backoff_ms
-       local ndry_runs = tonumber(redis.call('get', _:qk-ndry-runs) or 0)
-       local eoq_ms_tab = {_:eoq-ms0, _:eoq-ms1, _:eoq-ms2, _:eoq-ms3, _:eoq-ms4}
-       local eoq_backoff_ms = tonumber(eoq_ms_tab[math.min(5, (ndry_runs + 1))])
-
-       -- Set queue-wide polling backoff flag
-       redis.call('psetex', _:qk-eoq-backoff, eoq_backoff_ms, 'true')
-       redis.call('incr',   _:qk-ndry-runs)
-
-       return 'eoq-backoff'
-     end
-
-     local lock_exp    = tonumber(redis.call('hget', _:qk-locks,    mid) or 0)
-     local backoff_exp = tonumber(redis.call('hget', _:qk-backoffs, mid) or 0)
-
-     -- Active lock/backoff
-     if (now < lock_exp) or (now < backoff_exp) then return nil end
-
-     redis.call('set', _:qk-ndry-runs, 0) -- Doing useful work
-
-     if redis.call('sismember', _:qk-done, mid) == 1 then -- GC
-       redis.call('hdel',  _:qk-messages,   mid)
-       redis.call('hdel',  _:qk-locks,      mid)
-       redis.call('hdel',  _:qk-backoffs,   mid)
-       redis.call('hdel',  _:qk-nattempts,  mid)
-       redis.call('ltrim', _:qk-mid-circle, 1, -1)
-       redis.call('srem',  _:qk-done,       mid)
-       return nil
-     end
-
-     redis.call('hset', _:qk-locks, mid, now + tonumber(_:lock-ms)) -- Acquire
-     local mcontent  = redis.call('hget',    _:qk-messages,  mid)
-     local nattempts = redis.call('hincrby', _:qk-nattempts, mid, 1)
-     return {mid, mcontent, nattempts}"
+     (script-with-msg-status (not :mid-arg)
+      "--
+      if redis.call('exists', _:qk-eoq-backoff) == 1 then return 'eoq-backoff' end
+
+      -- TODO Waiting for Lua brpoplpush support to get us long polling
+      local mid = redis.call('rpoplpush', _:qk-mid-circle, _:qk-mid-circle)
+      local now = tonumber(_:now)
+
+      if (not mid) or (mid == 'end-of-circle') then -- Uninit'd or eoq
+
+        -- Calculate eoq_backoff_ms
+        local ndry_runs = tonumber(redis.call('get', _:qk-ndry-runs) or 0)
+        local eoq_ms_tab = {_:eoq-ms0, _:eoq-ms1, _:eoq-ms2, _:eoq-ms3, _:eoq-ms4}
+        local eoq_backoff_ms = tonumber(eoq_ms_tab[math.min(5, (ndry_runs + 1))])
+
+        -- Set queue-wide polling backoff flag
+        redis.call('psetex', _:qk-eoq-backoff, eoq_backoff_ms, 'true')
+        redis.call('incr',   _:qk-ndry-runs)
+
+        return 'eoq-backoff'
+      end"
+      ;; -- Get `state` local
+      "--
+
+      if (state == 'locked') or
+         (state == 'locked-with-requeue') or
+         (state == 'queued-with-backoff') or
+         (state == 'done-with-backoff') then return nil end
+
+      redis.call('set', _:qk-ndry-runs, 0) -- Doing useful work
+
+      if (state == 'done-awaiting-gc') then
+        redis.call('hdel',  _:qk-messages,   mid)
+        redis.call('hdel',  _:qk-locks,      mid)
+        redis.call('hdel',  _:qk-backoffs,   mid)
+        redis.call('hdel',  _:qk-nattempts,  mid)
+        redis.call('ltrim', _:qk-mid-circle, 1, -1)
+        redis.call('srem',  _:qk-done,       mid)
+        return nil
+      end
+
+      redis.call('hset', _:qk-locks, mid, now + tonumber(_:lock-ms)) -- Acquire
+      local mcontent  = redis.call('hget',    _:qk-messages,  mid)
+      local nattempts = redis.call('hincrby', _:qk-nattempts, mid, 1)
+      return {mid, mcontent, nattempts}")
      {:qk-messages    (qkey qname :messages)
       :qk-locks       (qkey qname :locks)
       :qk-backoffs    (qkey qname :backoffs)


Retrieving the :href values from the nested map. It would be easier/cleaner to use proper keys in the faction map instead of title strings.

--- scraper/src/scraper/core.clj
+++ scraper/src/scraper/core.clj
@@ -61,7 +61,8 @@
                            (first)
                            (by-tag :a))
                        )]
-    (map #(get-in % [:href]) the-factions)
+    (doseq [faction the-factions]
+      (println (:href (first (vals faction)))))
     ;(dotimes [i 10] (future (send-off url-col (parse "http://wiki.project1999.com/index.php?title=Category:Factions"))))
     )
   )


fixed linewrap

fixed linewrap

--- hyrax/src/clojure/hyrax/dist/rabbit.clj
+++ hyrax/src/clojure/hyrax/dist/rabbit.clj
@@ -251,7 +251,8 @@
   (let [ch (require-ch conn)
         queue-name (-> ch lq/declare :queue)
         handler (fn [ch {:keys [delivery-tag headers]} ^bytes payload]
-                  (let [^com.rabbitmq.client.LongString sender-wrapper (get headers "peer-id") ; rabbit driver weirdness
+                  (let [; rabbit driver weirdness
+                        ^com.rabbitmq.client.LongString sender-wrapper (get headers "peer-id")
                         sender-id (-> sender-wrapper
                                       (.getBytes)
                                       (String.))


null pointer exception fix

null pointer exception fix

--- src-clj/acha/achievement.clj
+++ src-clj/acha/achievement.clj
@@ -69,9 +69,10 @@
 (def hello-linus
   [:hello-linus
   (fn [commit-info]
-    (when (>= (:level ((second bad-motherfucker) commit-info)) 10))
+    (when-let [bad-acha ((second bad-motherfucker) commit-info)]
+    (when (>= (:level bad-acha) 10))
     {:username (:author commit-info)
-          :time (:time commit-info)})])
+          :time (:time commit-info)}))])

 (def borat
   (make-word-counting-scanner [:borat spellings/table]))


fix cond default case

fix cond default case

--- src-cljs/freactive/core.cljs
+++ src-cljs/freactive/core.cljs
@@ -16,7 +16,7 @@
 (defn get-binding-fns [iref]
   (cond
    (satisfies? IReactive iref) (-get-binding-fns iref)
-   iwatchable-binding-fns))
+   :default iwatchable-binding-fns))

 (def ^:dynamic *register-dep* nil)


Add support for cross experiment comparisons and STAR aligner

--- src/aerobio/htseq/rnaseq.clj
+++ src/aerobio/htseq/rnaseq.clj
@@ -83,6 +83,49 @@
   (apply get-comparison-files- args))

+(defn get-xcomparison-files-
+  "Compute the set of Cross Experiment comparison bams and the
+  corresponding output csv for the count table matrix. Cross
+  comparison sets are based on the CrossComparisonSheet.csv for the
+  pseudo experiment of eid (the pseudo experiment id). If rep? is
+  true, returns the comparison sets for replicates of comparison
+  pairs, else returns comparison sets for combined bams."
+  ([eid rep?]
+   (get-xcomparison-files- eid "ComparisonSheet.csv" rep?))
+  ([eid comp-filename rep?]
+   (let [bpath (if rep? [:rep :bams] [:bams])
+         fpath (if rep? [:rep :fcnts] [:fcnts])
+         fcnts (apply cmn/get-exp-info eid fpath)
+         compvec (->> comp-filename
+                      (fs/join (pams/get-params :nextseq-base) eid)
+                      slurp csv/read-csv rest
+                      (map (fn[[c1 c2]]
+                             (let [[eid1 strain cond1] (str/split #"-" c1)
+                                   gb1 (str strain "-" cond1 "*.bam")
+                                   c1bams (apply cmn/get-exp-info eid1 bpath)
+                                   [eid2 strain cond2] (str/split #"-" c2)
+                                   gb2 (str strain "-" cond2 "*.bam")
+                                   c2bams (apply cmn/get-exp-info eid2 bpath)]
+                               [(fs/join c1bams gb1) (fs/join c2bams gb2)]))))
+         bamsvec (mapv (fn[v] (mapcat #(-> % fs/glob sort) v)) compvec)
+         otcsvs (mapv (fn[v] (fs/join
+                             fcnts
+                             (str (cljstr/join
+                                   "-" (mapv #(->> % fs/basename
+                                                   (str/split #"\*")
+                                                   first)
+                                             v))
+                                  ".csv")))
+                      compvec)]
+     (mapv #(vector %1 %2) bamsvec otcsvs))))
+
+(defmethod cmn/get-xcomparison-files :rnaseq
+  [_ & args]
+  (apply get-xcomparison-files- args))
+
+
+
+
 (defn split-filter-fastqs
   [eid]
   (cmn/split-filter-fastqs eid identity))
@@ -101,16 +144,23 @@
 ;;; Get primary phase 1 arguments. These are the bowtie index, the
 ;;; fastq set, output bam and bai file names
 (defmethod cmn/get-phase-1-args :rnaseq
-  [_ eid repname & {:keys [repk]}]
+  [_ eid repname & {:keys [repk star]}]
   (let [fqs (cljstr/join "," (cmn/get-replicate-fqzs eid repname repk))
         refnm (cmn/replicate-name->strain-name eid repname)
         btindex (fs/join (cmn/get-exp-info eid :index) refnm)
+        starindex (when star
+                    (fs/join (cmn/get-exp-info eid :starindex) refnm))
+        starprefix (when star
+                     (fs/join (cmn/get-exp-info eid repk :star) repname))
         otbam (fs/join (cmn/get-exp-info eid repk :bams) (str repname ".bam"))
         otbai (str otbam ".bai")
         refgtf (fs/join (cmn/get-exp-info eid :refs)
                         (str refnm ".gtf"))]
     (apply cmn/ensure-dirs (map fs/dirname [otbam otbai]))
-    [btindex fqs otbam otbai]))
+    (when star (cmn/ensure-dirs (fs/dirname starprefix)))
+    (if star
+      [starindex fqs otbam otbai starprefix]
+      [btindex fqs otbam otbai])))

 (defn get-phase-2-dirs [eid repk]
@@ -141,6 +191,11 @@
     [repjob cfgjob]))

+#_(defmethod cmn/run-xcomparison :rnaseq
+  [_ eid recipient compfile get-toolinfo template]
+  (run-rnaseq-comparison
+   eid recipient compfile get-toolinfo template))
+
 (defmethod cmn/run-comparison :rnaseq
   [_ eid recipient compfile get-toolinfo template]
   (run-rnaseq-comparison


Minor change in calls-finalizer?

Minor change in calls-finalizer?

--- src/app/itemsOnLifecycle.clj
+++ src/app/itemsOnLifecycle.clj
@@ -170,7 +170,7 @@
 (defn calls-finalizers? [class]
   (->> (getMethods class)
        (map toStringWithoutComments)
-       (filter #(.contains % "finalize("))
+       (filter #(.contains % "finalize()"))
        (count)
        (pos?)))


rename VOID to STOP

rename VOID to STOP

--- src/clj/com/rpl/specter.cljx
+++ src/clj/com/rpl/specter.cljx
@@ -150,7 +150,7 @@
 (defpath
   ^{:doc "Stops navigation at this point. For selection returns nothing and for
           transformation returns the structure unchanged"}
-  VOID
+  STOP
   []
   (select* [this structure next-fn]
     nil )


Add function for updating UUIDs on instruction maps

I've only tested this function via the REPL. It is intended to be called
on every individual after it is produced via an operator.

--- src/clojush/pushgp/breed.clj
+++ src/clojush/pushgp/breed.clj
@@ -82,6 +82,20 @@
              rand-gen
              argmap))))

+(defn update-instruction-map-uuids
+  "Takes an individual and updates the UUIDs on every instruction-map in its
+   :geneome, except for the ones which are a random insertion."
+  [individual]
+  (update individual :genome
+          (fn [genome]
+            (map (fn [instruction-map]
+                   (if (:random-insertion instruction-map)
+                     (dissoc instruction-map :random-insertion)
+                     (assoc instruction-map
+                            :parent-uuid (:uuid instruction-map)
+                            :uuid (java.util.UUID/randomUUID))))
+                 genome))))
+
 (defn perform-genetic-operator
   "Takes a single genetic operator keyword or a sequence of operator keywords,
    and performs them to create a new individual. Uses recursive helper function


Updating for metadata db system changes.

--- src/cmr/bootstrap/system.clj
+++ src/cmr/bootstrap/system.clj
@@ -30,8 +30,7 @@
   "Returns a new instance of the whole application."
   []
   (let [metadata-db (-> (mdb-system/create-system "metadata-db-in-bootstrap-pool")
-                        (dissoc :log :web)
-                        (assoc :skip-background-jobs true))
+                        (dissoc :log :web :scheduler))
         indexer (-> (idx-system/create-system)
                     (dissoc :log :web)
                     ;; Setting the parent-collection-cache to cache parent collection umm


added problem 66

added problem 66

--- src/foreclojure/data_set.clj
+++ src/foreclojure/data_set.clj
@@ -684,6 +684,18 @@
             :restricted (map str '[class type Class vector? sequential?
                                    list? seq? map? set? getClass])})

+      )
+
+      (insert! :problems
+           {:_id 66
+            :title "Power Set"
+            :times-solved 0
+            :description "A power set is the set of all subsets of a given set. Given a list, produce a set of sublists while preserving the order of elements."
+            :tags ["medium" "seqs"]
+            :tests ["(= (__ '(1 :a)) #{'(1 :a) '(:a) '() '(1)})"
+                    "(= (__ '()) '())"
+                    "(= (__ '(1 2 3)) #{'() '(1) '(2) '(3) '(1 2) '(1 3) '(2 3) '(1 2 3)})"
+                    "(= (count (__ (range 10))) 1024)"]})
       ))

 (load-problems)


Send email when problem is accepted. Fixes #120.

--- src/foreclojure/problems.clj
+++ src/foreclojure/problems.clj
@@ -484,7 +484,7 @@
                                         :only [:approved :times-solved])
             approved (true? (:approved existing-problem))]

-        (when (empty? author)           ; newly submitted, not a moderator tweak
+        (when-not existing-problem
           (try
             (send-email
              {:from "team@4clojure.com"
@@ -529,12 +529,25 @@
 (defn approve-problem [id]
   "take a user submitted problem and approve it"
   (if (approver? (session/session-get :user))
-    (do
+    (let [{:keys [title user]} (from-mongo
+                                (fetch-one :problems
+                                           :where {:_id id}
+                                           :only [:title :user]))
+          url (str "/problem/" id)]
       (update! :problems
                {:_id id}
                {:$set {:approved true}})
+      (try
+        (send-email
+         {:from "team@4clojure.com"
+          :to [(users/email-address user)]
+          :subject (format "Problem #%d: submission accepted" id)
+          :html (html (link-to url title))
+          :text (str title ": " url)})
+        ;; TODO: dump this in a proper log
+        (catch EmailException e (println (str "email failed to send on approved problem #" id))))
       (flash-msg (str "Problem " id " has been approved!")
-                 (str "/problem/" id)))
+                 url))
     (flash-error "You don't have access to this page" "/problems")))

 (defn reject-problem [id reason]