bumped up dependencies

bumped up dependencies

--- src/leiningen/new/cryogen/project.clj
+++ src/leiningen/new/cryogen/project.clj
@@ -7,8 +7,8 @@
                            [ring/ring-devel "1.3.2"]
                            [compojure "1.3.1"]
                            [ring-server "0.3.1"]
-                           [cryogen-markdown "0.1.0"]
-                           [cryogen-core "0.1.16"]]
+                           [cryogen-markdown "0.1.1"]
+                           [cryogen-core "0.1.17"]]
             :plugins [[lein-ring "0.8.13"]]
             :main cryogen.core
             :ring {:init cryogen.server/init


piggieback is no longer a thing

piggieback is no longer a thing

--- src/leiningen/new/reagent/project.clj
+++ src/leiningen/new/reagent/project.clj
@@ -50,7 +50,7 @@
          :target-path "resources/public/css"}{{/less-hook?}}

   :profiles {:dev {:repl-options {:init-ns {{project-ns}}.repl
-                                  :nrepl-middleware [cemerick.piggieback/wrap-cljs-repl{{{nrepl-middleware}}}]}
+                                  :nrepl-middleware [{{{nrepl-middleware}}}]}

                    :dependencies [[ring-mock "0.1.5"]
                                   [ring/ring-devel "1.3.2"]


Add TODO

Add TODO

--- src/lens/middleware/wan_exception.clj
+++ src/lens/middleware/wan_exception.clj
@@ -11,5 +11,5 @@
         (pst-on *err* false e)
         {:status 500
          :body
-         {:links {:up {:href "/"}}
+         {:links {:up {:href "/"}}                          ;;TODO: use context path here
           :error (.getMessage e)}}))))


Fix broken library-version and logout methods. Close #4.

--- src/clj/hatnik/web/server/login.clj
+++ src/clj/hatnik/web/server/login.clj
@@ -84,9 +84,10 @@
     :session nil))

 (defn login-api-routes [db config]
-  (routes
-   (GET "/github" [code state] (github-login db config code state))
-   (GET "/current-user" req (current-user req))
-   (when (:enable-force-login config)
-     (GET "/force-login" [email] (force-login db email)))
-   (GET "/logout" [] (logout))))
+  (->> [(GET "/github" [code state] (github-login db config code state))
+        (GET "/current-user" req (current-user req))
+        (when (:enable-force-login config)
+          (GET "/force-login" [email] (force-login db email)))
+        (GET "/logout" [] (logout))]
+       (remove nil?)
+       (apply routes)))


Theme name is not a keyword

Theme name is not a keyword

--- src/cljs/asciinema_player/view.cljs
+++ src/cljs/asciinema_player/view.cljs
@@ -158,7 +158,7 @@
     [:div.loader]])

 (defn player-class-name [theme-name]
-  (str "asciinema-theme-" (name theme-name)))
+  (str "asciinema-theme-" theme-name))

 (defn player-style [] {})


small improvements to cardbrowser

small improvements to cardbrowser

--- src/cljs/netrunner/cardbrowser.cljs
+++ src/cljs/netrunner/cardbrowser.cljs
@@ -123,6 +123,11 @@
     (when (> (.scrollTop $cardlist) (- height 600))
       (om/update-state! owner :page inc))))

+(defn handle-search [e owner]
+  (doseq [filter [:set-filter :type-filter :sort-filter :faction-filter]]
+    (om/set-state! owner filter "All"))
+  (om/set-state! owner :search-query (.. e -target -value)))
+
 (defn card-browser [cursor owner]
   (reify
     om/IInitState
@@ -154,7 +159,7 @@
             (when-not (empty? query)
               [:span.e.search-clear {:dangerouslySetInnerHTML #js {:__html ""}
                                      :on-click #(om/set-state! owner :search-query "")}])
-            [:input.search {:on-change #(om/set-state! owner :search-query (.. % -target -value))
+            [:input.search {:on-change #(handle-search % owner)
                             :type "text" :placeholder "Search cards" :value query}]])

          [:div
@@ -164,7 +169,7 @@
            (for [field ["Faction" "Name" "Type" "Influence" "Cost" "Set number"]]
              [:option {:value field} field])]]

-         (for [filter [["Set" :set-filter (map :name (:sets cursor))]
+         (for [filter [["Set" :set-filter (map :name (sort-by :available (:sets cursor)))]
                        ["Side" :side-filter ["Corp" "Runner"]]
                        ["Faction" :faction-filter (factions (:side-filter state))]
                        ["Type" :type-filter (types (:side-filter state))]]]


apply fix to plugin modal routes function

--- src/cljs/salava/core/ui/helper.cljs
+++ src/cljs/salava/core/ui/helper.cljs
@@ -24,7 +24,7 @@
   Modal function is exported from own namespace e.g (defn ^:export modalroute [] {:key fname})"
   [plugins namespaces]
   (let [exported-routes (reduce (fn [r route] (conj r (first (plugin-fun plugins route "modalroute")))) [] namespaces)
-        modal-routes (into {} (reduce (fn [r mr] (conj r (mr))) [] exported-routes))]
+        modal-routes (into {} (reduce (fn [r mr] (conj r (mr))) [] (remove nil? exported-routes)))]

     modal-routes))


Unification of build-queue-fetcher

Unification of build-queue-fetcher

--- src/emender_jenkins/build_queue_fetcher.clj
+++ src/emender_jenkins/build_queue_fetcher.clj
@@ -17,9 +17,10 @@

 (require '[emender-jenkins.time-utils :as time-utils])

-(def started-on    (atom nil))
-(def finished-on   (atom nil))
-(def last-duration (atom nil))
+(def status (atom {
+    :started-on    nil
+    :finished-on   nil
+    :last-duration nil}))

 (defn fetch-data
     "Read job statuses and job results. Stores them in the data structure in result module."
@@ -36,34 +37,35 @@

 (defn run-fetcher-one-iteration
     "One iteration of job data fetcher."
-    [configuration]
+    [configuration fetch-data-function status-map]
     (log/info "Fetcher is reading job results")
     (let [start-time (System/currentTimeMillis)]
-        (try-to-fetch-data configuration)
+        (fetch-data-function configuration)
         (let [end-time (System/currentTimeMillis)
               duration (- end-time start-time)]
-              (reset! started-on  (time-utils/get-formatted-time start-time))
-              (reset! finished-on (time-utils/get-formatted-time end-time))
-              (reset! last-duration    duration)
+              (reset! status-map {
+                  :started-on    (time-utils/get-formatted-time start-time)
+                  :finished-on   (time-utils/get-formatted-time end-time)
+                  :last-duration duration})
               (log/info "Done in " duration "ms "))))

 (defn run-fetcher-in-a-loop
     "Run the fetcher periodically. The sleep amount should containg time delay
     in minutes."
-    [sleep-amount configuration]
+    [sleep-amount configuration fetch-data-function status-map]
     (let [ms-to-sleep (time-utils/compute-sleep-amount sleep-amount)]
         (while true
             (do
-                (run-fetcher-one-iteration configuration)
+                (run-fetcher-one-iteration configuration fetch-data-function status-map)
                 (log/info "Sleeping for" sleep-amount " minutes")
                 (Thread/sleep ms-to-sleep)))))

 (defn run-fetcher
     "Run the endless fetcher loop."
-    [configuration]
+    [configuration fetch-data-function status-map]
     (let [sleep-amount  (-> configuration :fetcher :build-queue-fetcher-delay)]
         (log/info "Fetcher started in its own thread, configured sleep amount: " sleep-amount)
-        (run-fetcher-in-a-loop sleep-amount configuration)))
+        (run-fetcher-in-a-loop sleep-amount configuration fetch-data-function status-map)))

 (defn run-fetcher-in-thread
     "Run the fetcher (its loop) in a separate thread."
@@ -72,5 +74,5 @@
         (log/info "starting build queue fetcher")
         (log/debug "delay" (-> configuration :fetcher :build-queue-fetcher-delay))
         ; he have to use lambda here because we need to pass parameter into the run-fetcher function
-        (.start (Thread. #(run-fetcher configuration)))))
+        (.start (Thread. #(run-fetcher configuration fetch-data status)))))


Renamed to a-input and z-output for sortability.

--- src/cbfg/world-example0.cljs
+++ src/cbfg/world-example0.cljs
@@ -35,13 +35,13 @@
     (vis-init (fn [world]
                 (let [in-ch (achan-buf world 100)
                       out-ch (achan-buf world 0)]
-                  (ago-loop user-in world [num-ins 0]
+                  (ago-loop a-input world [num-ins 0]
                             (let [cmd (<! cmd-ch)
                                   cmd-handler ((get example-cmd-handlers (:op cmd)) cmd)]
-                              (aput user-in in-ch cmd-handler)
+                              (aput a-input in-ch cmd-handler)
                               (recur (inc num-ins))))
-                  (ago-loop user-out world [num-outs 0]
-                            (let [result (atake user-out out-ch)]
+                  (ago-loop z-output world [num-outs 0]
+                            (let [result (atake z-output out-ch)]
                               (set-el-innerHTML (str el-prefix "-output") result)
                               (recur (inc num-outs))))
                   (make-fenced-pump world in-ch out-ch @example-max-inflight)))


Refactor to remove dependency on java.classpath and use java.io

--- src/main/clojure/clojure/tools/namespace.clj
+++ src/main/clojure/clojure/tools/namespace.clj
@@ -16,12 +16,43 @@
   ^{:author "Stuart Sierra",
      :doc "Search for ns declarations in dirs, JARs, or CLASSPATH"}
   clojure.tools.namespace
-  (:require [clojure.java.classpath :as classpath]
+  (:require [clojure.java.io :as io]
             [clojure.set :as set])
   (import (java.io File FileReader BufferedReader PushbackReader
                    InputStreamReader)
-          (java.util.jar JarFile)))
+          (java.util.jar JarFile JarEntry)))

+;;; JAR-file utilities, adapted from clojure.java.classpath
+
+(defn- jar-file?
+  "Returns true if file is a normal file with a .jar or .JAR extension."
+  [f]
+  (let [file (io/file f)]
+    (and (.isFile file)
+         (or (.endsWith (.getName file) ".jar")
+             (.endsWith (.getName file) ".JAR")))))
+
+(defn- jar-files
+  "Given a sequence of File objects, filters it for JAR files, returns
+  a sequence of java.util.jar.JarFile objects."
+  [files]
+  (map #(JarFile. ^File %) (filter jar-file? files)))
+
+(defn- filenames-in-jar
+  "Returns a sequence of Strings naming the non-directory entries in
+  the JAR file."
+  [^JarFile jar-file]
+  (map #(.getName ^JarEntry %)
+       (filter #(not (.isDirectory ^JarEntry %))
+               (enumeration-seq (.entries jar-file)))))
+
+(defn- jar-file?
+  "Returns true if file is a normal file with a .jar or .JAR extension."
+  [f]
+  (let [file (io/file f)]
+    (and (.isFile file)
+         (or (.endsWith (.getName file) ".jar")
+             (.endsWith (.getName file) ".JAR")))))

 ;;; Finding namespaces in a directory tree

@@ -67,15 +98,15 @@
   "Attempts to read a (ns ...) declaration from file, and returns the
   unevaluated form.  Returns nil if read fails, or if the first form
   is not a ns declaration."
-  [^File file]
-  (with-open [rdr (PushbackReader. (BufferedReader. (FileReader. file)))]
+  [file]
+  (with-open [rdr (PushbackReader. (io/reader file))]
     (read-ns-decl rdr)))

 (defn find-ns-decls-in-dir
   "Searches dir recursively for (ns ...) declarations in Clojure
   source files; returns the unevaluated ns declarations."
   [^File dir]
-  (filter identity (map read-file-ns-decl (find-clojure-sources-in-dir dir))))
+  (keep read-file-ns-decl (find-clojure-sources-in-dir dir)))

 (defn find-namespaces-in-dir
   "Searches dir recursively for (ns ...) declarations in Clojure
@@ -89,7 +120,7 @@
 (defn clojure-sources-in-jar
   "Returns a sequence of filenames ending in .clj found in the JAR file."
   [^JarFile jar-file]
-  (filter #(.endsWith ^String % ".clj") (classpath/filenames-in-jar jar-file)))
+  (filter #(.endsWith ^String % ".clj") (filenames-in-jar jar-file)))

 (defn read-ns-decl-from-jarfile-entry
   "Attempts to read a (ns ...) declaration from the named entry in the
@@ -97,9 +128,8 @@
   fails, or if the first form is not a ns declaration."
   [^JarFile jarfile ^String entry-name]
   (with-open [rdr (PushbackReader.
-                   (BufferedReader.
-                    (InputStreamReader.
-                     (.getInputStream jarfile (.getEntry jarfile entry-name)))))]
+                   (io/reader
+                    (.getInputStream jarfile (.getEntry jarfile entry-name))))]
     (read-ns-decl rdr)))

 (defn find-ns-decls-in-jarfile
@@ -118,24 +148,26 @@
   (map second (find-ns-decls-in-jarfile jarfile)))

-;;; Finding namespaces anywhere on CLASSPATH
+;;; Finding namespaces

-(defn find-ns-decls-on-classpath
-  "Searches CLASSPATH (both directories and JAR files) for Clojure
-  source files containing (ns ...) declarations.  Returns a sequence
-  of the unevaluated ns declaration forms."
-  []
+(defn find-ns-decls
+  "Searches a sequence of java.io.File objects (both directories and
+  JAR files) for .clj source files containing (ns...) declarations.
+  Returns a sequence of the unevaluated ns declaration forms. Use with
+  clojure.java.classpath to search Clojure's classpath."
+  [files]
   (concat
-   (mapcat find-ns-decls-in-dir (classpath/classpath-directories))
-   (mapcat find-ns-decls-in-jarfile (classpath/classpath-jarfiles))))
+   (mapcat find-ns-decls-in-dir (filter #(.isDirectory ^File %) files))
+   (mapcat find-ns-decls-in-jarfile (jar-files files))))

-(defn find-namespaces-on-classpath
-  "Searches CLASSPATH (both directories and JAR files) for Clojure
-  source files containing (ns ...) declarations.  Returns a sequence
-  of the symbol names of the declared namespaces."
-  []
-  (map second (find-ns-decls-on-classpath)))
-
+(defn find-namespaces
+  "Searches a sequence of java.io.File objects (both directories and
+  JAR files) for .clj source files containing (ns...) declarations.
+  Returns a sequence of the symbol names of the declared
+  namespaces. Use with clojure.java.classpath to search Clojure's
+  classpath."
+  [files]
+  (map second (find-ns-decls files)))

 ;;; Parsing dependencies

@@ -157,8 +189,8 @@
     (apply set/union (map #(deps-from-libspec nil %) (rest form)))))

 (defn deps-from-ns-decl
-  "Given a (quoted) ns declaration, returns a set of symbols naming
-  the dependencies of that namespace.  Handles :use and :require
-  clauses but not :load."
+  "Given an (ns...) declaration form (unevaluated), returns a set of
+  symbols naming the dependencies of that namespace.  Handles :use and
+  :require clauses but not :load."
   [decl]
   (apply set/union (map deps-from-ns-form decl)))


remove a done TODO

remove a done TODO

--- src/puppetlabs/cthun/websockets.clj
+++ src/puppetlabs/cthun/websockets.clj
@@ -34,8 +34,6 @@
     (jetty-adapter/idle-timeout! ws idle-timeout)
     (cs/add-connection host ws)))

-; TODO(ploubser): Action on valid message
-; Forward non server messages to intended destination
 (defn- on-text!
   "OnMessage (text) websocket event handler"
   [ws message]


(PDB-3993) command-service: guard resource cleanup in stop method

Make sure resources that don't exist until the start method has
finished are only cleaned up if they exist.

--- src/puppetlabs/puppetdb/command.clj
+++ src/puppetlabs/puppetdb/command.clj
@@ -653,10 +653,9 @@
              :consumer-threadpool command-threadpool)))

   (stop [this {:keys [consumer-threadpool command-chan delay-pool] :as context}]
-    (async/close! command-chan)
-    (gtp/shutdown consumer-threadpool)
-    (when delay-pool
-      (stop-and-reset-pool! delay-pool))
+    (some-> command-chan async/close!)
+    (some-> consumer-threadpool gtp/shutdown)
+    (some-> delay-pool stop-and-reset-pool!)
     (async/unsub-all (:response-pub context))
     (async/untap-all (:response-mult context))
     (async/close! (:response-chan-for-pub context))


PDOK-1599 error handling extracts

PDOK-1599 error handling extracts

--- src/main/clojure/pdok/featured/extracts.clj
+++ src/main/clojure/pdok/featured/extracts.clj
@@ -31,7 +31,12 @@
   "Returns the rendered representation of the collection of features for a given feature-type inclusive tiles-set"
   (let [template (template templates-dir dataset feature-type extract-type)
         partials (partials templates-dir dataset extract-type)]
-    (map #(vector (:_tiles %) (m/render template % partials) (:_valid_from %) (:_valid_to %)) features)))
+    (if (or (nil? template) (nil? partials))
+      [(str "Template or partials cannot be found for dataset: " dataset
+                                                    " feature-type: " feature-type
+                                                    " extract-type: " extract-type
+                                                    " template-dir: " templates-dir) nil]
+      [nil (map #(vector (:_tiles %) (m/render template % partials) (:_valid_from %) (:_valid_to %)) features)])))

 (defn create-extract-collection [db table]
@@ -68,13 +73,20 @@
   (do
    (create-extract-collection config/data-db table)
    (doseq [[tiles xml-feature valid-from valid-to] rendered-features]
-     (jdbc-insert db table valid-from valid-to (vec tiles) xml-feature nil)))))
+     (jdbc-insert db table valid-from valid-to (vec tiles) xml-feature nil))
+   {:count (count rendered-features)})))

 (defn fill-extract [dataset collection extract-type extract-version]
   (let [feature-type collection
         features (timeline/all (config/timeline) dataset collection)
-        features-for-extract (features-for-extract dataset feature-type extract-type features "src/main/resources/pdok/featured/templates")]
-      (add-extract-records config/data-db dataset feature-type extract-type extract-version features-for-extract)))
+        [error features-for-extract] (features-for-extract dataset
+                                                           feature-type
+                                                           extract-type
+                                                           features
+                                                           "src/main/resources/pdok/featured/templates")]
+    (if (nil? error)
+      (add-extract-records config/data-db dataset feature-type extract-type extract-version features-for-extract)
+      {:error error})))

 (defn file-to-features [path dataset]
   "Helper function to read features from a file.


Updtate snap to ppa and trigger CI

Updtate snap to ppa and trigger CI

--- main/src/dda/pallet/dda_managed_vm/infra/office.clj
+++ main/src/dda/pallet/dda_managed_vm/infra/office.clj
@@ -56,9 +56,11 @@
 (defn install-pdf-chain
   [facility]
   (actions/as-action
-   (logging/info (str facility "-install system: pdf-chain")))
+    (logging/info (str facility "-install system: pdf-chain")))
   ;(actions/packages :aptitude ["pdfchain" "pdftk" "gprename" "pyrenamer" "a2ps"])
-  (actions/exec-script ("snap" "install" "pdftk")))
+  ;(actions/exec-script ("snap" "install" "pdftk"))
+  (actions/packages :aptitude ["pdftk-java"])
+  )

 (defn install-audio
   [facility]


Make Clojure Test More Like Joker

Make Clojure Test More Like Joker

--- tests/eval/multi-methods/bat.cljc
+++ tests/eval/multi-methods/bat.cljc
@@ -1,6 +1,6 @@
 (ns-unmap *ns* 'bat)

-(def N #?(:clj Number
+(def N #?(:clj Long
           :joker Int))

 (defmulti-joke bat


Fixed reading openbadges metadata in cases where the chunk is after IDAT.

--- src/clj/salava/badge/png.clj
+++ src/clj/salava/badge/png.clj
@@ -13,6 +13,7 @@

 (defn get-png-metadata [file]
   (let [reader (init-reader file)
+        _ (.readSkippingAllRows reader)
         metadata (.getMetadata reader)
         openbadges-data (.getTxtForKey metadata "openbadges")]
     (if (blank? openbadges-data)
@@ -24,4 +25,4 @@
         hosted? (re-find #"\{" data)]
     (if hosted?
       (get-in (json/read-str data :key-fn keyword) [:verify :url])
-      (signed-assertion data))))+      (signed-assertion data))))


File from jars are not Files bu InputStreams

--- src/clj_crud/system/ring.clj
+++ src/clj_crud/system/ring.clj
@@ -100,7 +100,11 @@
                          (let [res (handler req)]
                            (info "File res: " res)
                            (if (and (= :get (:request-method req))
-                                    (instance? java.io.File (:body res)))
+                                    ;; File when using localhost
+                                    ;; InputStream when running from
+                                    ;; jar on Heroku
+                                    (or (instance? java.io.InputStream (:body res))
+                                        (instance? java.io.File (:body res))))
                              (assoc-in res [:headers "Cache-Control"] "public, max-age=31536000")
                              res)))))
                     file-info/wrap-file-info


rework validation paths

rework validation paths

--- src/clj_money/validation.clj
+++ src/clj_money/validation.clj
@@ -18,48 +18,58 @@
        (pos? (count value))))

 (defn- interpret-empty-string-failure
-  [problem]
-  (when (and (symbol? (:pred problem))
-             (= 'non-empty-string? (:pred problem)))
-    (let [attribute (-> problem :path first)]
-      [attribute (format "%s cannot be empty" (humanize attribute))])))
+  [{:keys [path pred]}]
+  (when (and (symbol? pred)
+             (= 'non-empty-string? pred))
+    [path (format "%s cannot be empty" (humanize (last path)))]))

 (defn- interpret-regex-failure
-  [problem]
-  (when (and (coll? (:pred problem))
-             (= 're-matches (-> problem :pred second)))
-    (let [attribute (-> problem :path first)]
-      [attribute (format "%s is not valid" (humanize attribute))])))
+  [{:keys [path pred]}]
+  (when (and (coll? pred)
+             (= 're-matches (second pred)))
+    [path (format "%s is not valid" (humanize (last path)))]))

 (defn- interpret-required-failure
-  [problem]
-  (when (and (coll? (:pred problem))
-             (= 'contains? (-> problem :pred first)))
-    (let [attribute (-> problem :pred (nth 2))]
-      [attribute (format "%s is required" (humanize attribute))])))
+  [{:keys [path pred]}]
+  (when (and (coll? pred)
+             (= 'contains? (first pred)))
+    [[(nth pred 2)] (format "%s is required" (humanize (nth pred 2)))]))

 (defn- interpret-set-inclusion-failure
-  [problem]
-  (when (set? (:pred problem))
-    (let [attribute (-> problem :path first)]
-      [attribute
-       (format "%s must be one of: %s"
-               (humanize attribute)
-               (->> problem
-                    :pred
-                    (map name)
-                    (string/join ", ")))])))
+  [{:keys [pred path]}]
+  (when (set? pred)
+    [path
+     (format "%s must be one of: %s"
+             (humanize (last path))
+             (->> pred
+                  (map name)
+                  (string/join ", ")))]))
+
+(defn- interpret-collection-count-failure
+  [{:keys [pred path]}]
+  (when (and (seq? pred)
+             (or (= (first pred) '<=)
+                 (= (first pred) 'clojure.core/<=)))
+    [(first path)
+     (format "Count must be greater than or equal to %s" (second pred))]))
+
+(defn- interpret-unknown-failure
+  [{:keys [pred path] :as problem}]
+  (pprint {:interpret-unknown-failure problem
+           :class (class pred)})
+  [path (format "The attribute at %s is not valid" path)])

 (def problem-interpreters
   [interpret-required-failure
    interpret-regex-failure
    interpret-empty-string-failure
-   interpret-set-inclusion-failure])
+   interpret-collection-count-failure
+   interpret-set-inclusion-failure
+   interpret-unknown-failure])

 (defn- problem->message
   [problem]
-  (or (some #(% problem) problem-interpreters)
-      (throw (RuntimeException. (str "Unable to make sense of the problem: " problem)))))
+  (some #(% problem) problem-interpreters))

 (defn- interpret-problems
   [explanation]
@@ -67,7 +77,7 @@
        :clojure.spec/problems
        (map problem->message)
        (reduce (fn [result [k message]]
-                 (update-in result [k] (fnil #(conj % message) [])))
+                 (update-in result k (fnil #(conj % message) [])))
                {})))

 (defn- perform-additional-validation


Add apropos and shorter-named apro to clj-ns-browser.utils

--- src/clj_ns_browser/utils.clj
+++ src/clj_ns_browser/utils.clj
@@ -387,3 +387,65 @@
               (when (zero? (:exit (clojure.java.shell/sh "bash" "-c" (str "[ -f " p " ]"))))
                 (assoc m :file p)))))))))

+
+(defn unresolve
+  "Given a var, return a sequence of all symbols that resolve to the
+var from the current namespace *ns*."
+  [var]
+  (when-not (instance? clojure.lang.Var var)
+    (throw (Exception. (format "unresolve: first arg must be Var"))))
+  (let [home-ns (.ns var)
+        sym-name-str (second (re-find #"/(.*)$" (str var)))]
+    (sort-by
+     #(count (str %))
+     (concat
+      ;; The symbols in the current namespace that map to the var, if
+      ;; any
+      (->> (ns-map *ns*)
+           (filter (fn [[k v]] (= var v)))
+           (map first))
+      ;; This is the "canonical" symbol that resolves to the var, with
+      ;; full namespace/symbol-name
+      (list (symbol (str home-ns) sym-name-str))
+      ;; There might be one or more aliases for the symbol's home
+      ;; namespace defined in the current namespace.
+      (->> (ns-aliases *ns*)
+           (filter (fn [[ns-alias ns]] (= ns home-ns)))
+           (map first)
+           (map (fn [ns-alias-symbol]
+                  (symbol (str ns-alias-symbol) sym-name-str))))))))
+
+
+(defn apropos
+  "Given a regular expression or stringable thing, calculate a
+sequence of all symbols in all currently-loaded namespaces such that
+it matches the str-or-pattern, with at most one such symbol per Var.
+The sequence returned contains symbols that map to those Vars, and are
+the shortest symbols that map to the Var, when qualified with the
+namespace name or alias, if that qualification is necessary to name
+the Var.  Note that it is possible the symbol returned does not match
+the str-or-pattern itself, e.g. if the symbol-to-var mapping was
+created with :rename.
+
+Searches through all non-Java symbols in the current namespace, but
+only public symbols of other namespaces."
+  [str-or-pattern & opts]
+  (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern)
+                   #(re-find str-or-pattern (str %))
+                   #(.contains (str %) (str str-or-pattern)))]
+    (map #(first (unresolve %))
+         (set
+          (mapcat (fn [ns]
+                    (map second
+                         (filter (fn [[s v]] (matches? s))
+                                 (if (= ns *ns*)
+                                   (concat (ns-interns ns) (ns-refers ns))
+                                   (ns-publics ns)))))
+                  (all-ns))))))
+
+
+(defn apro
+  "Shorter-name version of apropos that also sorts and pretty-prints
+the results."
+  [str-or-pattern & opts]
+  (clojure.pprint/pprint (sort (apply apropos str-or-pattern opts))))


changed symbols-of-ns-coll to use fqname to obtain the fqn for a var or class, which makes both vars and classes show up correctly for "FQN Listing" and for multiple-ns selection

--- src/clj_ns_browser/utils.clj
+++ src/clj_ns_browser/utils.clj
@@ -17,8 +17,10 @@
         [clojure.pprint :only [pprint]]
         [clj-info.doc2map :only [get-docs-map]]
         [clj-info.doc2txt :only [doc2txt]]
-        [clj-info.doc2html :only [doc2html]]))
-
+        [clj-info.doc2html :only [doc2html]]
+        [alex-and-georges.debug-repl]))
+
+(declare fqname)

 ;; Two convenience function for clojure.tools.trace
 ;; that should ideally be part of that library
@@ -106,13 +108,15 @@
                                          :display-str (str k)
                                          :name-to-search (str k)})
             :ns-map-subset (fn [[sym var-or-class]]
-                             (let [fqn-sym (when (instance? clojure.lang.Var
-                                                            var-or-class)
-                                             ;; TBD: There is probably
-                                             ;; a faster way to do
-                                             ;; this.
-                                             (symbol (str (.ns var-or-class))
-                                                     (str sym)))
+                             (let [fqn-str-or-nil (fqname var-or-class)
+                                   fqn-sym (when fqn-str-or-nil (symbol fqn-str-or-nil))
+;;                                             (when (instance? clojure.lang.Var
+;;                                                             var-or-class)
+;;                                              ;; TBD: There is probably
+;;                                              ;; a faster way to do
+;;                                              ;; this.
+;;                                              (symbol (str (.ns var-or-class))
+;;                                                      (str sym)))
                                    ds (if (and display-fqn? fqn-sym)
                                         fqn-sym
                                         sym)]


species.cljx edited online with Bitbucket

--- src/cljx/oxylab/species.cljx
+++ src/cljx/oxylab/species.cljx
@@ -1,25 +1,91 @@
 (ns oxylab.species)

 (def species
-  {:scryopus {:size 1.0
-              :max-size 10.0
-              :min-size 0.5
-              :production-rate 0.001
-              :tolerance {:detrit {:model :range
-                                   :ideal 5.0
-                                   :radius 5.0}
-                          :acid {:model :limit
-                                 :ideal 5.0
-                                 :radius 1.0}}
-              :influence {:detrit -0.005
-                          :soil 0.005}}
-
-   :abracada {:size 2.0
+{:cyanobacteria {:size 0.3e20
+               :max-size 1e20
+               :min-size 100
+               :production-rate 0.02
+               :influence {:detrit 1e-20
+                           :oxygen 1e-20}}
+:lichens {:size 0.3e6
+         :max-size 1e6
+         :min-size 10
+         :production-rate 2e-3
+         :influence {:detrit 0.4e-6
+                     :oxygen 0.2e-6}}
+:soilbacteria {:size 0.3e30
+              :max-size 1e30
+              :min-size 100
+              :production-rate 0.05
+              :tolerance {:detrit {:model :limit
+                                   :ideal 1.2e-30
+                                   :radius -1.2e-30}}
+              :influence {:detrit -0.9e-30
+                          :soil 1e-30}}
+:fungus {:size 0.3e9
+        :max-size 1e10
+        :min-size 100
+        :production-rate 1e-2
+        :tolerance {:detrit {:model :limit
+                             :ideal 1.4e-10
+                             :radius -1.4e-10}}
+        :influence {:detrit -1e-10
+                    :soil 1.3e-10}}
+:moss {:size 0.3e6
+      :max-size 1e6
+      :min-size 10
+      :production-rate 1e-5
+      :tolerance {:soil {:model :limit
+                         :ideal 1
+                         :radius -0.5}}
+      :influence {:detrit 3e-6
+                  :oxygen 3e-6
+                  :soil -1e-6}}
+:herbs {:size 300
+       :max-size 1e4
+       :min-size 5
+       :production-rate 0.01
+       :tolerance {:soil {:model :limit
+                          :ideal 1.3
+                          :radius -0.6}}
+       :influence {:detrit 5e-4
+                   :oxygen 4e-4
+                   :soil -1.2e-4}}
+:worms {:size 500
+       :max-size 1e3
+       :min-size 3
+       :production-rate 1e-3
+       :tolerance {:detrit {:model :limit
+                            :ideal 8
+                            :radius -5}}
+       :influence {:detrit -9e-3
+                   :soil 6e-3}}
+:insects {:size 1e4
+         :max-size 1e4
+         :min-size 2
+         :production-rate 0.39e-1
+         :tolerance {:detrit {:model :limit
+                              :ideal 10
+                              :radius -6}}
+         :influence {:detrit -13e-4
+                     :soil 10e-4}}
+:bushes {:size 2
+        :max-size 100
+        :min-size 2
+        :production-rate 2e-3
+        :tolerance {:soil {:model :limit
+                           :ideal 6
+                           :radius -1}}
+        :influence {:detrit 6e-2
+                    :oxygen 0.2
+                    :soil -0.06}}
+:foliar_trees {:size 1
+              :max-size 20
               :min-size 1
-              :max-size 1000.0
-              :production-rate 0.05
+              :production-rate 1e-3
               :tolerance {:soil {:model :limit
-                                 :ideal 5.0
-                                 :radius -3.0}}
-              :influence {:soil -0.0005
-                          :oxygen 0.01}}})
+                                 :ideal 10
+                                 :radius -1}}
+              :influence {:detrit 0.4
+                          :oxygen 2
+                          :soil -0.5}}})


fix indentation

fix indentation

--- src/clojure/duratom/core.clj
+++ src/clojure/duratom/core.clj
@@ -139,17 +139,18 @@
 (defn- add-sync-error-handler
   [backend handle-error]
   (letfn [(backend* []
-            (delay (with-meta backend
-                       {:error-handler
-                        (if (nil? handle-error)
-                          ut/noop
-                          (fn [e]
-                            (try (handle-error e recommit*)
-                                 ;; swallow error-handler exceptions
-                                 ;; much like an agent would
-                                 (catch Exception _
-                                   ;(println "swallowed" _)
-                                   nil))))})))
+            (delay
+              (with-meta backend
+                         {:error-handler
+                          (if (nil? handle-error)
+                            ut/noop
+                            (fn [e]
+                              (try (handle-error e recommit*)
+                                   ;; swallow error-handler exceptions
+                                   ;; much like an agent would
+                                   (catch Exception _
+                                     ;(println "swallowed" _)
+                                     nil))))})))
           (recommit* [] ((recommit-fn @(backend*))))]
     @(backend*)))


break up threads-list

break up threads-list

--- src/clueweb_disqus/posts.clj
+++ src/clueweb_disqus/posts.clj
@@ -1,9 +1,13 @@
 (ns clueweb-disqus.posts
   "Codebase for reading thread listings
    and downloading individual posts"
-  (:require [clojure.java.io :as io]
-            [clojure.string :as string])
-  (:import [java.io File PushbackReader]))
+  (:require [clj-time.core :as t]
+            [clj-time.coerce :as c]
+            [clojure.java.io :as io]
+            [clojure.string :as string]
+            [clueweb-disqus.core :as core])
+  (:import [java.io File PushbackReader])
+  (:use [clojure.pprint :only [pprint]]))

 (defn threads-list-files
   [a-directory]
@@ -20,6 +24,21 @@
     (file-seq
      (File. a-directory)))))

+(defn thread-ids-list-files
+  [a-directory]
+  (map
+   #(.getAbsolutePath %)
+   (filter
+    (fn [f]
+      (and
+       (re-find #".*-disqus-threads-.*.threads$"
+                (.getAbsolutePath f))
+       (not
+        (re-find #"bkup"
+                 (.getAbsolutePath f)))))
+    (file-seq
+     (File. a-directory)))))
+
 (defn threads-list-seq
   [a-file]
   (let [rdr (-> a-file
@@ -58,3 +77,182 @@
   (let [files (threads-list-files a-directory)]
     (doseq [a-file files]
       (dump-thread-ids a-file))))
+
+(def posts-endpoint "https://disqus.com/api/3.0/posts/list.json")
+
+(defn create-url
+  ([thread-id api-key]
+     (create-url thread-id api-key nil))
+  ([thread-id api-key cursor]
+     (str posts-endpoint
+          "?api_key="
+          api-key
+          "&thread="
+          thread-id
+          "&order=asc"
+          "&limit=100"
+          (if cursor (str "&cursor=" cursor) ""))))
+
+(defn write-content
+  [filename-to-write body]
+  (let [content-to-write (get body "response")]
+    (do (with-open [wrtr (io/writer filename-to-write :append true)]
+          (doall
+           (doseq [c content-to-write]
+             (pprint c wrtr)))))))
+
+(defn discover-iteration
+  [thread-id filename-to-write first-page-content api-key]
+  (let [next-pg-check (-> first-page-content
+                          (get "cursor")
+                          (get "hasNext"))]
+    (if next-pg-check ; pagination exists
+      (let [cursor-value (-> first-page-content
+                             (get "cursor")
+                             (get "next"))
+
+            next-pg-url (create-url thread-id
+                                    api-key
+                                    cursor-value)
+
+            next-pg-content (core/rate-limited-download next-pg-url)]
+        (write-content filename-to-write
+                       next-pg-content)
+        (recur thread-id filename-to-write next-pg-content api-key))
+
+      (println :thread-posts-finished))))
+
+(defn download-posts
+  "Download all the posts for a single thread"
+  [thread-id file-to-write api-key]
+  (let [url (create-url thread-id
+                        api-key)
+        first-page-content (core/rate-limited-download url)]
+    (write-content file-to-write first-page-content)
+    (discover-iteration thread-id file-to-write first-page-content api-key)))
+
+(defn load-credentials
+  []
+  (-> "credentials-posts.clj"
+      slurp
+      read-string))
+
+(defn get-api-key-for-start-epoch
+  [credentials since-epoch]
+  (or (-> credentials (get (str since-epoch)) :api-key)
+      (let [orig-epochs (keys credentials)
+            correct-key (str
+                         (first
+                          (last
+                           (sort-by
+                            first
+                            (filter
+                             (fn [[e d]]
+                               (pos? d))
+                             (map
+                              vector
+                              (map #(Long/parseLong %) orig-epochs)
+                              (map #(- since-epoch (Long/parseLong %))
+                                   orig-epochs)))))))]
+        (-> credentials (get correct-key) :api-key))))
+
+(defn download-posts-for-threads
+  [thread-ids-file]
+  (let [file-to-write (string/replace thread-ids-file
+                                      #".threads$"
+                                      ".posts.lock")
+
+        final-file (string/replace thread-ids-file
+                                   #".threads$"
+                                   ".posts")
+
+        associated-epoch (first
+                          (string/split
+                           (last
+                            (string/split thread-ids-file #"/"))
+                           #"-"))
+
+        credentials (load-credentials)
+
+        deja-downloaded-file (string/replace thread-ids-file
+                                             #".threads$"
+                                             ".downloaded")
+
+        downloaded (if (.exists
+                        (io/as-file deja-downloaded-file))
+                     (set
+                      (string/split-lines
+                       (slurp deja-downloaded-file)))
+                     (set []))]
+    (if-not (.exists
+             (io/as-file file-to-write))
+
+      ;; rename existing file
+      (do (when (.exists
+                 (io/as-file final-file))
+            (.rename (io/as-file final-file)
+                     (io/as-file file-to-write)))
+
+          ;; kick off download
+          (let [thread-ids (filter
+                            (fn [t]
+                              (not
+                               (some #{t} downloaded)))
+                            (string/split-lines
+                             (slurp thread-ids-file)))]
+            (do (doseq [thread-id thread-ids]
+                  (download-posts thread-id
+                                  file-to-write
+                                  (get-api-key-for-start-epoch
+                                   credentials
+                                   (Long/parseLong associated-epoch))))
+
+                ;; rename back the file
+                (.rename (io/as-file file-to-write)
+                         (io/as-file final-file))
+
+                ;; now record the download thread-ids
+                (with-open [wrtr (io/writer deja-downloaded-file :append true)]
+                  (doall
+                   (doseq [thread-id thread-ids]
+                     (binding [*out* wrtr]
+                       (println thread-id))))))))
+
+      (println :crawl-in-progress))))
+
+(defn break-up-threads-list
+  []
+  (let [threads-listing (str core/disqus-jobs-dir "all.threads")
+        downloaded-listing (if (.exists
+                                (io/as-file "all.downloaded"))
+                            (set
+                             (string/split-lines
+                              (slurp "all.downloaded")))
+                            (set []))
+        thread-stream (with-open [rdr (io/reader threads-listing)]
+                        (doall
+                         (filter
+                          (fn [x]
+                           (not
+                            (some #{x} downloaded-listing)))
+                          (line-seq rdr))))
+
+        num-threads (count thread-stream)
+
+        size-of-batches (quot num-threads 8)
+
+        credentials (keys
+                     (load-credentials))
+
+        keys-threads-stream
+        (map vector credentials (partition size-of-batches thread-stream))]
+
+    (doseq [[k ts] keys-threads-stream]
+      (with-open [wrtr (io/writer
+                        (str core/disqus-jobs-dir k "-thread-ids" ".threads")
+                        :append
+                        true)]
+        (doall
+         (doseq [t ts]
+           (binding [*out* wrtr]
+             (println t))))))))


Removed keyword hint (wasn't always true).

--- src/cmr/sample_data/core.clj
+++ src/cmr/sample_data/core.clj
@@ -12,7 +12,7 @@
 (defn get-ges-disc-provider
   ([]
     (get-ges-disc-provider :data))
-  ([^Keyword as-data]
+  ([as-data]
     (util/get-file (str const/providers-resource "/GES_DISC.json") as-data)))

 (defn get-ges-disc-airx3std-collection
@@ -31,9 +31,10 @@

 (defn get-ges-disc-airx3std-collection-metadata
   ([]
-    (get-ges-disc-airx3std-collection :json))
+    (get-ges-disc-airx3std-collection-metadata :json))
   ([^Keyword file-type]
-    (get-ges-disc-airx3std-collection file-type const/default-handler-key))
+    (get-ges-disc-airx3std-collection-metadata
+     file-type const/default-handler-key))
   ([^Keyword file-type as-data]
     (case file-type
       :json (util/get-file
@@ -58,7 +59,7 @@
     (get-ges-disc-airx3std-ch4-variable filename-part :json))
   ([filename-part ^Keyword file-type]
     (get-ges-disc-airx3std-ch4-variable filename-part file-type :data))
-  ([filename-part ^Keyword file-type ^Keyword as-data]
+  ([filename-part ^Keyword file-type as-data]
     (util/get-file
       (format "%s/GES_DISC/AIRX3STD/CH4/CH4_%s.%s"
               const/variables-resource
@@ -69,7 +70,7 @@
 (defn get-ges-disc-airx3std-ch4-variables
   ([]
    (get-ges-disc-airx3std-ch4-variables :obj))
-  ([^Keyword as-data]
+  ([as-data]
    (util/get-files
     (str const/variables-resource "/GES_DISC/AIRX3STD/CH4")
     as-data)))


Implement read-batch in index code.

Implement read-batch in index code.

--- src/merkle_db/index.clj
+++ src/merkle_db/index.clj
@@ -1,6 +1,10 @@
 (ns merkle-db.index
   "The index tree in a table is a B+ tree which orders the partitions into a
-  sorted tree structure."
+  sorted tree structure.
+
+  An empty data tree is represented by a nil link from the table. A data tree
+  with fewer records than the partition limit is represented directly by a
+  single partition node."
   (:require
     [clojure.future :refer [pos-int?]]
     [clojure.spec :as s]
@@ -24,3 +28,113 @@
                   ::children])
     #(= (count (::children %))
         (inc (count (::keys %))))))
+
+
+
+;; ## Information Functions
+
+; TODO: list partitions
+; TODO: group partitions into roughly equal sizes
+
+
+
+;; ## Read Functions
+
+(defn read-all
+  "Read a lazy sequence of key/map tuples which contain the requested field data
+  for every record in the subtree. This function works on both index nodes and
+  partitions."
+  [store node fields]
+  (case (:data/type node)
+    :merkle-db/index-node
+    (mapcat
+      (fn read-child
+        [child-link]
+        (if-let [child (node/get-data store child-link)]
+          (read-all store child fields)
+          (throw (ex-info (format "Missing child linked from index-node %s: %s"
+                                  (:id node) child-link)
+                          {:node (:id node)
+                           :child child-link}))))
+      (::children node))
+
+    :merkle-db/partition
+    (part/read-all store node fields)
+
+    (throw (ex-info (str "Unsupported data-tree node type: "
+                         (pr-str (:data/type node)))
+                    {:data/type (:data/type node)}))))
+
+
+(defn- assign-keys
+  "Assigns record keys to the children of this node which they would belong
+  to. Returns a lazy sequence of vectors containing the child index and a
+  sequence of record keys."
+  [split-keys record-keys]
+  (->>
+    [nil 0 split-keys record-keys]
+    (iterate
+      (fn [[_ index splits rks]]
+        (when (seq rks)
+          (if (seq splits)
+            ; Take all records coming before the next split key.
+            (let [[in after] (split-with (partial key/before? (first splits)) rks)]
+              [[index in] (inc index) (next splits) after])
+            ; No more splits, emit one final group with any remaining keys.
+            [[(inc index) rks]]))))
+    (drop 1)
+    (take-while first)
+    (map first)))
+
+
+(defn read-batch
+  "Read a lazy sequence of key/map tuples which contain the requested field data
+  for the records whose keys are in the given collection. This function works on
+  both index nodes and partitions."
+  [store node fields record-keys]
+  (case (:data/type node)
+    :merkle-db/index-node
+    (mapcat
+      (fn read-child
+        [[index child-keys]]
+        (let [child-link (nth (::children node) index)]
+          (if-let [child (node/get-data store child-link)]
+            (read-batch store child fields child-keys)
+            (throw (ex-info (format "Missing child linked from index-node %s: %s"
+                                    (:id node) child-link)
+                            {:node (:id node)
+                             :child child-link})))))
+      (assign-keys (::keys node) record-keys))
+
+    :merkle-db/partition
+    (part/read-batch store node fields record-keys)
+
+    (throw (ex-info (str "Unsupported data-tree node type: "
+                         (pr-str (:data/type node)))
+                    {:data/type (:data/type node)}))))
+
+
+; TODO: read-range
+; narrow children by which could contain the range, recurse in order
+
+
+; TODO: read-slice
+; narrow children by which could contain the range, recurse in order
+
+
+
+;; ## Update Functions
+
+; TODO: update-records!
+
+
+
+;; ## Deletion Functions
+
+; TODO: remove-batch
+
+
+; TODO: remove-range
+
+
+; TODO: remove-slice


Fix namespace-aliases not processing all clauses

The :require-macros and :use-macros clauses were previously unprocessed
but these clauses also hold libspecs which might be aliased.

--- src/refactor_nrepl/ns/ns_parser.clj
+++ src/refactor_nrepl/ns/ns_parser.clj
@@ -101,15 +101,22 @@
                (map #(set/rename-keys % {:only :refer}))))))

 (defn get-libspecs-from-file
-  "Opts are the same as those expected by tools.namespace's
-  read-ns-decl."
+  "Return all the libspecs in a file.
+
+  This is the concatenation of all the libspecs found in the use,
+  use-macros, require and require-macros forms.
+
+  Note that no post-processing is done so there might be duplicates or
+  libspecs which could have been combined or eliminated as unused.
+
+  Opts are the same as those expected by tools.namespace's
+  read-ns-decl and the default is to allow reader conditionals and
+  read :clj."
   ([^File f]
-   (some->> f
-            .getAbsolutePath
-            (read-ns-form)
-            get-libspecs))
+   (get-libspecs-from-file {:features #{:clj} :read-cond :allow} f))
   ([opts ^File f]
    (some->> f
             .getAbsolutePath
             (read-ns-form opts)
-            get-libspecs)))
+            ((juxt get-libspecs get-required-macros))
+            (mapcat identity))))


Finished problem 2.48 which converts a number to its float representation using 1 sign bit, 8 exp bits and 23 float bits for a total of 32 bit float

--- src/computer_systems/ch2.clj
+++ src/computer_systems/ch2.clj
@@ -626,3 +626,35 @@
 ;(complete-whole-float-table {:s 1 :e 2 :f 2}) ;solves the problem!

+;Practice Problem 2.48
+;As mentioned in Problem 2.6, the integer 3,510,593 has hexadecimal representa- tion 0x00359141, while the single-precision, floating-point number 3510593.0 has hexadecimal representation 0x4A564504. Derive this floating-point representa- tion and explain the correlation between the bits of the integer and floating-point representations.
+
+(defn get-significant-bits [bit-vec]
+  (subvec (vec bit-vec) (.indexOf (apply str bit-vec) "1")))
+
+(defn right-pad [bit-vec size]
+  (concat bit-vec (take (- size (count bit-vec)) (repeat 0))))
+
+
+
+(defn get-float-bits-from-number [n]
+  (let
+      [non-padded-f
+       (rest ;drop the first bit (it is a 1), this is because it is always a 1 and can be implied
+        (get-significant-bits
+         (decimal-to-binary n 32)))
+
+       pow (count non-padded-f)]
+
+    (concat
+     (if (< n 0) [1] [0])
+     (decimal-to-binary (+ 127 pow) 8)
+     (right-pad non-padded-f 23))))
+
+
+;(get-float-bits-from-number 3510593)
+;=>(0 1 0 0 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0)
+;(hex-to-binary "00359141")
+;=>(0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1)
+
+; 101011001000101000001 is the float portion and it is the same the first 1 on the hex representation is dropped due to its implicitness


Fix typo in spec (#147)

Fix typo in spec (#147)

Thanks @AdamFrey, sorry about the delay in merging!

--- src/crucible/aws/kinesis.clj
+++ src/crucible/aws/kinesis.clj
@@ -9,6 +9,6 @@

 (s/def ::stream (s/keys :req [::shard-count]
                         :opt [::name
-                              :crucible.resourcs/tags]))
+                              :crucible.resources/tags]))

 (defresource stream "AWS::Kinesis::Stream" ::stream)


remove unused namespace

remove unused namespace


accept float on the seconds value

accept float on the seconds value


Flatline notification

Flatline notification

--- src/node/game/core.cljs
+++ src/node/game/core.cljs
@@ -24,19 +24,19 @@
      (swap! state update-in [side :deck] (partial drop n))))

 (defn flatline [state]
-  (prn "flatline"))
+  (system-msg state :runner "is flatlined"))

 (defn damage [state side type n]
   (let [hand (get-in @state [:runner :hand])]
-    (if (< (count hand) n)
-      (flatline state)
-      (do (when (= type :brain)
-            (swap! state update-in [:runner :brain-damage] inc)
-            (swap! state update-in [:runner :max-hand-size] dec))
-          (let [shuffled-hand (shuffle hand)
-                discarded (zone :discard (take n shuffled-hand))]
-            (swap! state update-in [:runner :discard] #(concat % discarded))
-            (swap! state assoc-in [:runner :hand] (drop n shuffled-hand)))))))
+    (when (< (count hand) n)
+      (flatline state))
+    (do (when (= type :brain)
+          (swap! state update-in [:runner :brain-damage] inc)
+          (swap! state update-in [:runner :max-hand-size] dec))
+        (let [shuffled-hand (shuffle hand)
+              discarded (zone :discard (take n shuffled-hand))]
+          (swap! state update-in [:runner :discard] #(concat % discarded))
+          (swap! state assoc-in [:runner :hand] (drop n shuffled-hand))))))

 (defn do! [{:keys [cost effect]}]
   (fn [state side args]
@@ -145,11 +145,11 @@

 (defn play-instant [state side card]
   (when (pay state side :click 1 :credit (:cost card) (when (has? card :subtype "Double") [:click 1]))
+    (system-msg state side (str "plays " (:title card) "."))
     (move state side card :play-area)
     (when-let [effect (get-in game.cards/cards [(:title card) :effect])]
       (effect state side card))
-    (move state side (first (get-in @state [side :play-area])) :discard)
-    (system-msg state side (str "plays " (:title card) "."))))
+    (move state side (first (get-in @state [side :play-area])) :discard)))

 (defn runner-install [state side card]
   (when (pay state side :click 1 :credit (:cost card) :memory (:memoryunits card))


added exterminate behaviour

added exterminate behaviour

--- src/test/clojure/naojure/sample.clj
+++ src/test/clojure/naojure/sample.clj
@@ -35,6 +35,7 @@
 (nao/run-behaviour robot "dsnowdon-happy" ch1)
 (nao/run-behaviour robot "dsnowdon-angry" ch1)
 (nao/run-behaviour robot "dsnowdon-scared" ch1)
+(nao/run-behaviour robot "dsnowdon-exterminate" ch1)

 ;; complete movement in default time
 (nao/donao


Fix auth handler test.

Fix auth handler test.

--- test/lunchlotto/auth/handlers_test.clj
+++ test/lunchlotto/auth/handlers_test.clj
@@ -93,7 +93,8 @@
                                :latitude              42.123
                                :longitude             -42.123}}]
     (testing "successfully confirm user"
-      (with-redefs [models/confirm-user (fn [_ _])]
+      (with-redefs [models/confirm-user (fn [_ _])
+                    models/find-user-by-email (fn [_ _])]
         (let [resp (handlers/confirm-user valid-params)]
           (is (= 302 (:status resp)))
           (is (= {"Location" "/lunches/upcoming"} (:headers resp)))


fix parse method so it could handle json written as string ("{\"a\": \"b\"}")


allow empty :entries for :npm-module again

was removed together with classpath indexing but is useful in
some cases.

fixes #831

--- src/main/shadow/build/targets/npm_module.clj
+++ src/main/shadow/build/targets/npm_module.clj
@@ -11,20 +11,23 @@
             [shadow.build.targets.browser :as browser]
             [clojure.spec.alpha :as s]
             [shadow.build.config :as config]
-            [shadow.build.node :as node]))
+            [shadow.build.node :as node]
+            [shadow.build.classpath :as classpath]
+            [shadow.build.test-util :as tu]))

 (s/def ::runtime #{:node :browser :react-native})

 (s/def ::entries
-  (s/coll-of simple-symbol? :kind vector? :min-count 1 :distinct true))
+  (s/coll-of simple-symbol? :kind vector? :distinct true))

 (s/def ::target
   (s/keys
     :req-un
     [::shared/output-dir
-     ::entries]
+     ]
     :opt-un
-    [::runtime
+    [::entries
+     ::runtime
      ::shared/devtools]))

 (defmethod config/target-spec :npm-module [_]
@@ -60,10 +63,22 @@

 (defn resolve* [module-config {:keys [classpath] :as state} mode {:keys [entries runtime] :as config}]
   (let [repl?
-        (some? (:worker-info state))]
+        (some? (:worker-info state))
+
+        entries
+        (cond
+          (seq entries)
+          (vec entries)
+
+          ;; FIXME: this isn't really about testing but the options may fit
+          (contains? config :ns-regexp)
+          (tu/find-test-namespaces classpath config)
+
+          :all
+          (classpath/find-cljs-namespaces-in-files classpath nil))]

     (-> module-config
-        (assoc :entries (vec entries))
+        (assoc :entries entries)
         (cond->
           (and repl? (or (= :browser runtime) (nil? runtime)))
           (-> (browser/inject-repl-client state config)


remove leftover debug log message

remove leftover debug log message

--- src/main/shadow/cljs/devtools/api.clj
+++ src/main/shadow/cljs/devtools/api.clj
@@ -268,8 +268,6 @@
           (set! *nrepl-clj-ns* *ns*)
           (set! *ns* (create-ns 'cljs.user))

-          (log/warn ::nrepl-select-output-loop *nrepl-quit-signal*)
-
           ;; nrepl doesn't have a clear way to signal the end of a session
           ;; so this keeps running even is the nrepl is disconnected
           ;; I hope the print just fails and kills the loop?


Add fn to jump to an argument

Add fn to jump to an argument

--- src/discuss/communication/main.cljs
+++ src/discuss/communication/main.cljs
@@ -182,4 +182,12 @@
 (defn resend-last-api
   "Resends stored url from last api call."
   []
-  (ajax-get (lib/get-last-api)))+  (ajax-get (lib/get-last-api)))
+
+(defn jump-to-argument
+  "Jump directly into the discussion to let the user argue about the given argument.
+
+   ** TODO: Update route **"
+  [slug arg-id]
+  (let [url (clojure.string/join "/" ["api" slug "jump" arg-id])]
+    (ajax-get url)))


add thoughts on random numbers

add thoughts on random numbers

--- src/mccarthy_animation/character.cljc
+++ src/mccarthy_animation/character.cljc
@@ -18,16 +18,26 @@
 (defn- load-images []
   (zipmap image-keys (map load-one-image image-keys)))

+(defn select-random-state
+  "Selects a state to do things at perceived random times.  However, it's being called
+100/second and has to be consistent during the animation.   We use the clock on a 21 second
+timer doing things every now and then. Another option would be to use a seeded PSEUDO-random
+number generator, but to do that rquires dropping into Java or JS and not really worth the
+effort."
+  []
+  (let [timer-cycle 21
+        n (mod (int (/ (quil/millis) 1000)) timer-cycle)]
+    (cond
+      (= 10 n) :blink
+      (= 19 n) :tap
+      :else :stand)))
+
 (defn get-animation-state [keystroke]
   (cond (= :right keystroke) :move
         (= :left  keystroke) :move
         (= :up    keystroke) :move
         (= :down  keystroke) :move
-        :else                (let [n (mod (int (/ (quil/millis) 1000)) 20)]
-                               (cond
-                                 (= 10 n) :blink
-                                 (= 19 n) :tap
-                                 :else :stand))))
+        :else                (select-random-state)))

 (defn- animated-keyword [base-name n speed]
   (let [s (* speed (/ (quil/millis) 1000.0))


Add cyclic edge-finding routine.

Add cyclic edge-finding routine.

--- src/edu/berkeley/ai/util/graphs.clj
+++ src/edu/berkeley/ai/util/graphs.clj
@@ -1,7 +1,7 @@
 (ns edu.berkeley.ai.util.graphs
   (:import [java.util Stack HashSet HashMap LinkedList])
-  (:use clojure.test  edu.berkeley.ai.util edu.berkeley.ai.util.queues edu.berkeley.ai.util.disjoint-sets)
-  )
+  (:use clojure.test edu.berkeley.ai.util edu.berkeley.ai.util.queues edu.berkeley.ai.util.disjoint-sets
+        edu.berkeley.ai.util.lp))

 ;;;; Incremental directed acyclic graphs for cycle detection (only).

@@ -164,6 +164,49 @@
            [scc (get rev-sccs outgoing)]))
        sccs])))

+
+
+
+(defn find-cyclic-edges
+  "Take a directed edge list, list of source nodes, and list of target nodes, a
+   and return a list of edges that do not participate in any acylic path from
+   a source node to a target node.  Uses a circuit-based LP solving method."
+  [edge-list sources sinks]
+  (let [nodes     (distinct (apply concat edge-list))
+        all-nodes (set (concat nodes [::SOURCE ::SINK]))
+        all-edges (concat edge-list
+                          (for [source sources] [::SOURCE source])
+                          (for [sink sinks]     [sink     ::SINK]))
+        out-map   (map-vals #(map second %) (unsorted-group-by first all-edges))
+        in-map    (map-vals #(map first %)  (unsorted-group-by second all-edges))]
+    (map key
+     (filter #(and (not (all-nodes (key %))) (= 0 (val %)))
+       (first
+        (solve-lp-clp
+         (make-lp
+          (into {}
+                (concat
+                 [[::SOURCE [0 0]]
+                  [::SINK   [1 1]]]
+                 (for [node nodes]     [node [nil nil]])
+                 (for [edge all-edges] [edge [0 nil]])))
+          (into {} (for [edge all-edges] [edge -1])) ; Minimize current
+          (into {}
+                (concat
+                 (for [node nodes] ;; Current conservation
+                   [(into {}
+                          (concat
+                           (for [in  (in-map node)]  [[in node]   1])
+                           (for [out (out-map node)] [[node out] -1])))
+                    [0 0]])
+                 (for [[s t :as edge] all-edges] ;; I >= v_t - v_s
+                   [{edge 1, s 1, t -1} [0 nil]]))))))))))
+
+(deftest find-cyclic-edges
+  (is (= (find-cyclic-edges [[:s :t] [:t :u] [:t :x]] [:s] [:u]) [[:t :x]]))
+  (is (= (find-cyclic-edges [[:s :t] [:t :u] [:t :x] [:x :t]] [:s] [:u]) [[:t :x] [:x :t]]))
+  (is (= (find-cyclic-edges [[:s :t] [:t :u] [:t :x] [:x :t] [:x :u]] [:s] [:u]) [[:x :t]]))
+  (is (= (find-cyclic-edges [[:s :t] [:t :u] [:t :x] [:x :t] [:x :u] [:s :x]] [:s] [:u]) [])))


add some docstrings to reap.clj

add some docstrings to reap.clj

--- src/fscrawler_tika_convert/reap.clj
+++ src/fscrawler_tika_convert/reap.clj
@@ -14,10 +14,12 @@
   (.scheduleWithFixedDelay scheduled-executor ^Runnable f 0 n TimeUnit/MILLISECONDS))

-(def future-map (atom {}))
+(def ^:private future-map (atom {}))

 (defn register-future!
+  "register future, on-error will be called if the future exits with an exception, otherwise
+  on exit will be called"
   [a-future on-error on-exit]
   (swap! future-map assoc a-future {:on-error on-error :on-exit on-exit}))

@@ -40,6 +42,8 @@

 (defn- mark-watcher-alive
+  "print a log message each minute, so we know the reaper is still
+ alive"
   []
   (swap! call-counter inc)
   (when (zero? (rem @call-counter 240))
@@ -69,5 +73,6 @@

 (defn start-watching-futures!
+  "start watching futures registered with register-future!"
   []
   (periodically 250 watch-futures))


fixed bug found by Matthew O'Connor

fixed bug found by Matthew O'Connor

--- src/name/choi/joshua/fnparse/json.clj
+++ src/name/choi/joshua/fnparse/json.clj
@@ -230,9 +230,9 @@
   (binding [*remainder-accessor* remainder-a] ; this is completely
                                               ; optional
     (rule-match text
-      #(raise parse-error "invalid document \"%s\""
+      #(raise parse-error % "invalid document \"%s\""
          (apply-str (remainder-a %)))
-      #(raise parse-error "leftover data after a valid node \"%s\""
+      #(raise parse-error %2 "leftover data after a valid node \"%s\""
          (apply-str (remainder-a %2)))
       (struct state-s tokens 0 0))))
 ; The call to rule-match above is equivalent to the stuff below:


Extract status/jobs-with-status

Extract status/jobs-with-status

--- src/overseer/status.clj
+++ src/overseer/status.clj
@@ -3,16 +3,21 @@
   (:require [datomic.api :as d]
             [clojure.set :as set]))

+(defn jobs-with-status [db status]
+  (->> (d/q '[:find ?jid
+              :in $ ?status
+              :where
+              [?e :job/status ?status]
+              [?e :job/id ?jid]]
+            db
+            status)
+       (map first)
+       (set)))
+
 (defn jobs-failed
   "Find all jobs that have failed."
   [db]
-  (->> (d/q '[:find ?jid
-              :where
-              [?e :job/status :failed]
-              [?e :job/id ?jid]]
-            db)
-       (map first)
-       (into #{})))
+  (jobs-with-status db :failed))

 (defn jobs-unfinished
   "Find all jobs that are not yet complete."
@@ -29,13 +34,7 @@
 (defn jobs-started
   "Find all jobs that are currently started."
   [db]
-  (->> (d/q '[:find ?jid
-              :where
-              [?e :job/status :started]
-              [?e :job/id ?jid]]
-            db)
-       (map first)
-       (into #{})))
+  (jobs-with-status db :started))

 (defn jobs-ready
   "Find all jobs that are ready to run.


don't insert a non-callback

don't insert a non-callback

--- src/pc/http/talaria.clj
+++ src/pc/http/talaria.clj
@@ -221,7 +221,9 @@
 (defn combine-callbacks [callbacks]
   (reduce (fn [acc cb]
             (if (fn? cb)
-              (juxt acc cb)
+              (if (fn? acc)
+                (juxt acc cb)
+                cb)
               acc))
           callbacks))


Updated iToC auxiliary functions

Updated iToC auxiliary functions

--- src/research_clojure/eChild/Child.clj
+++ src/research_clojure/eChild/Child.clj
@@ -115,7 +115,7 @@
   Only works for full, not
   necessarily with CHILDES distribution"
   [infoList grammar]
-  (if (and (isDeclarative (get infoList 1)) (= (in? (get infoList 2) "S") false) (outOblique (get infoList 2)))
+  (if (and (isDeclarative (get infoList 1)) (not (in? (get infoList 2) "S")) (outOblique (get infoList 2)))
     (assoc grammar 4 1)
     grammar))

@@ -123,7 +123,7 @@
 (defn setNullTopic
   "6th parameter"
   [sentence grammar]
-  (if (and (in? sentence "02") (= (in? sentence "01") false))
+  (if (and (in? sentence "02") (not (in? sentence "01")))
     (assoc grammar 5 1)
     grammar))

@@ -131,7 +131,7 @@
 (defn setWHMovement
   "7th parameter"
   [sentence grammar]
-  (if (and (> (.indexOf sentence "+WH") 0) (= (in? sentence "03[+WH]") false))
+  (if (and (> (.indexOf sentence "+WH") 0) (not (in? sentence "03[+WH]")))
     (assoc grammar 6 0)
     grammar))

@@ -164,64 +164,64 @@
     (do (def i (.indexOf sentence "01"))
         (def j (.indexOf sentence "Verb"))
         (if (and (> i 0) (not= j -1) (not= (Math/abs (- i j)) 1))
-          (assoc grammar 9 "1")
+          (assoc grammar 9 1)
           grammar))
     grammar))

 (defn iToC_aux1
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "0") (= g1 "0") (= g2 "0") (S_Aux sentence))
-    (assoc grammar 10 "0")
+  (if (and (= g0 0) (= g1 0) (= g2 0) (S_Aux sentence))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux2
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "1") (= g1 "1") (= g2 "1") (Aux_S sentence))
-    (assoc grammar 10 "0")
+  (if (and (= g0 1) (= g1 1) (= g2 1) (Aux_S sentence))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux3
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "1") (= g1 "0") (= g2 "1") (Aux_Verb sentence))
-    (assoc grammar 10 "0")
+  (if (and (= g0 1) (= g1 0) (= g2 1) (Aux_Verb sentence))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux4
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "0") (= g1 "1") (= g2 "0") (Verb_Aux sentence))
-    (assoc grammar 10 "0")
+  (if (and (= g0 0) (= g1 1) (= g2 0) (Verb_Aux sentence))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux5
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "0") (= g1 "0") (= g2 "1") (S_Aux sentence))
-    (assoc grammar 10 "0")
+  (if (and (= g0 0) (= g1 0) (= g2 1) (S_Aux sentence))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux6
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "1") (= g1 "1") (= g2 "0") (Aux_S sentence))
-    (assoc grammar 10 "0")
+  (if (and (= g0 1) (= g1 1) (= g2 1) (Aux_S sentence))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux7
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "1") (= g1 "0") (= g2 "0") (or (Never_Verb sentence) (hasKa sentence)))
-    (assoc grammar 10 "0")
+  (if (and (= g0 1) (= g1 0) (= g2 0) (or (Never_Verb sentence) (hasKa sentence)))
+    (assoc grammar 10 0)
     grammar))

 (defn iToC_aux8
   [g0 g1 g2 sentence grammar]
-  (if (and (= g0 "0") (= g1 "1") (= g2 "1") (or (Verb_Never sentence) (hasKa sentence)))
-    (assoc grammar 10 "0")
+  (if (and (= g0 0) (= g1 1) (= g2 1) (or (Verb_Never sentence) (hasKa sentence)))
+    (assoc grammar 10 0)
     grammar))


Fix markdown test

Fix markdown test

--- test/hu/ssh/github_changelog/formatters/markdown_test.clj
+++ test/hu/ssh/github_changelog/formatters/markdown_test.clj
@@ -11,7 +11,7 @@
 (def v-minor (c/complete {:minor 1 :patch 0, :pre-release nil :build nil} Semver))
 (def v-patch (c/complete {:patch 1 :pre-release nil :build nil} Semver))
 (def v-pre-release (c/complete {:pre-release "pre" :build nil} Semver))
-(def v-build (c/complete {:build "42"} Semver))
+(def v-build (c/complete {:pre-release "pre" :build "42"} Semver))

 (deftest highlight-fn
          (are [function version] (= (f-markdown/highlight-fn version) function)


unit test fix.

unit test fix.

--- test/metabase/driver/generic_sql/query_processor_test.clj
+++ test/metabase/driver/generic_sql/query_processor_test.clj
@@ -4,7 +4,7 @@
             [colorize.core :as color]
             [expectations :refer :all]
             [metabase.driver :as driver]
-            [metabase.driver.query-processor :refer [max-result-rows]]
+            [metabase.driver.query-processor :refer [max-result-bare-rows]]
             [metabase.test.data :refer [db-id table->id field->id]]))

 ;; # ERROR RESPONSES
@@ -14,7 +14,7 @@
     {:status :failed
      :error (str "Column \"CHECKINS.NAME\" not found; SQL statement:\nSELECT \"CHECKINS\".\"ID\", CAST(\"DATE\" AS DATE), "
                  "\"CHECKINS\".\"VENUE_ID\", \"CHECKINS\".\"USER_ID\" FROM \"CHECKINS\" WHERE (\"CHECKINS\".\"NAME\" = ?) LIMIT "
-                 max-result-rows)}
+                 max-result-bare-rows)}
   ;; This will print a stacktrace. Better to reassure people that that's on purpose than to make people question whether the tests are working
   (do (log/info (color/green "NOTE: The following stacktrace is expected <3"))
       (driver/process-query {:database @db-id


Reverse the order of the options and creator arguments

--- src/io/aviso/rook/server.clj
+++ src/io/aviso/rook/server.clj
@@ -49,7 +49,7 @@

   The extra logging and debugging middleware is added around the root handler (or the
   reloading handler that creates the root handler)."
-  [creator {:keys [reload log debug]} & creator-args]
+  [{:keys [reload log debug]} creator & creator-args]
   (let [handler (if reload
                   (-> #(apply creator creator-args) reloading-handler)
                   (apply creator creator-args))]


(maint) Fix one-handed equality zipper test

--- test/puppetlabs/puppetdb/zip_test.clj
+++ test/puppetlabs/puppetdb/zip_test.clj
@@ -129,8 +129,8 @@
     (is (= node tree))))

 (deftest test-map-traversal
-  (is (= {2 {2 {2 "foo"}}})
-      (post-order-transform (tree-zipper {1 {1 {1 "foo"}}})
-                            [(fn [node]
-                               (when (instance? clojure.lang.MapEntry node)
-                                 (update node 0 inc)))])))
+  (is (= {2 {2 {2 "foo"}}}
+         (:node (post-order-transform (tree-zipper {1 {1 {1 "foo"}}})
+                                      [(fn [node]
+                                         (when (instance? clojure.lang.MapEntry node)
+                                           (update node 0 inc)))])))))


Got it working

Got it working

--- src/journal_creator/core.clj
+++ src/journal_creator/core.clj
@@ -58,8 +58,6 @@
         end-date     (t/plus current-date (t/months 1))]
     (month-seq current-date end-date (t/days 1))))

-(def journal-format (fn [] "MMMM dd, yyyy, EEEE"))
-(def filename-date-format "yyyy-MM-dd")

 (defn get-today []
   (t/to-time-zone (t/now) (t/default-time-zone)))
@@ -76,41 +74,31 @@
 (defn file-format [file]
   (str file ".wiki"))

-(defn add-x-days-to-today [x]
-  (t/plus (get-today) (t/days x)))
+(def journal-format "MMMM dd, yyyy, EEEE")
+(defn convert-to-journal-header [date]
+  (f/unparse (custom-formatter journal-format) date))
+
+(def filename-date-format "yyyy-MM-dd")
+(defn convert-to-filename-extension [date]
+  (f/unparse (custom-formatter filename-date-format) date))

 (defn get-journal-header [date]
-  (journal-header-format (f/unparse (f/formatter-local  "MMMM dd, yyyy, EEEE") date )))
+  (journal-header-format (convert-to-journal-header date)))

-;; (def get-journal-header
-  ;; (comp journal-header-format unparse-today custom-formatter))
-
-(def get-filename
-  (comp file-format unparse-today custom-formatter))
-
+(defn get-filename-extension [date]
+  (file-format (convert-to-filename-extension date)))
+
 (defn -main
   [& args]
   (println "Today is: " (get-journal-header (get-today)))
-  ;; (println "file format is: " (get-filename filename-date-format))
-  ;; (spit (get-filename filename-date-format) (get-journal-header journal-format))
-  ;; (loop [i 1]
-    ;; (println (add-x-days-to-today i))
-    ;; (if (< i 10)
-      ;; (recur (inc i))))
- (prn "time-range")
- (loop [days (number-of-days-in-month 2017 03)]
-   (when (not (empty? days))
-     (let [day (first days)
-           journal-header (get-journal-header day)
-           ;; filename (formate-date file-format day)
-           ]
-       (prn "remaining:" (count days) "journal-header: " journal-header)
-       ;; (prn "filename: " filename)
-       ;; (spit filename journal-header)
-       (recur (rest days)))))
+  (println "file format is: " (get-filename-extension (get-today)))
+  (loop [days (number-of-days-in-month 2017 03)]
+    (when (seq days)
+      (let [day (first days)
+            journal-header (get-journal-header day)
+            filename (get-filename-extension day)]
+        (prn "remaining:" (count days) "journal-header: " journal-header)
+        (prn "filename: " filename)
+        (spit filename journal-header)
+        (recur (rest days))))))

- (loop [i (read-line)]
-    (println "row " (type i) i)
-    (if (= i "bye")
-      (println "All done!")
-      (recur (read-line)))))


using hash map for input env

using hash map for input env

--- test/celestial/integration/workflows/ec2.clj
+++ test/celestial/integration/workflows/ec2.clj
@@ -27,31 +27,30 @@
           (wf/reload (spec)) => nil
           (wf/destroy (spec)) => nil)

-      (fact "vpc public ip" :vpc :integration :ec2
-        (when-let [subnet (System/getenv "VPC_SUB")]
+      (fact "vpc public ip" :integration :ec2 :vpc
+        (when-let [{:keys [subnet id]} (clojure.edn/read-string (System/getenv "VPC"))]
           (s/update-system 1
             (spec {
               :machine {:os :ubuntu-14.04}
-              :aws { :vpc {:assign-public true :subnet-id subnet} }}))
+              :aws { :vpc {:assign-public true :subnet-id subnet :vpc-id id} }}))
           (wf/create (spec)) => nil
           (wf/stop (spec)) => nil
           (wf/reload (spec)) => nil
           (wf/destroy (spec)) => nil))

       (fact "vpc eip" :integration :ec2 :vpc
-        ; will be run only if VPC_SUB env var is defined
-        (when-let [eip (System/getenv "EIP")]
-          (when-let [subnet (System/getenv "VPC_SUB")]
+        ; will be run only if VPC env var is defined
+        (when-let [{:keys [eip id subnet]} (clojure.edn/read-string (System/getenv "VPC"))]
            (s/update-system 1
               (spec {:machine {:ip eip :os :ubuntu-14.04}
-                     :aws {:vpc {:subnet-id subnet}}}))
+                     :aws {:vpc {:subnet-id subnet :vpc-id id}}}))
            (wf/create (spec)) => nil
            (:machine (spec)) => (contains {:ip eip})
            (wf/stop (spec)) => nil
            (wf/reload (spec)) => nil
            (instance-desc (get-spec :aws :endpoint) (get-spec :aws :instance-id))
               => (contains {:public-ip-address eip})
-           (wf/destroy (spec)) => nil)))
+           (wf/destroy (spec)) => nil))

       (fact "aws eip workflows" :integration :ec2 :workflow
         ; will be run only if EIP env var is defined


Refactor, remove duplications

Refactor, remove duplications

--- scripts/gosync.clj
+++ scripts/gosync.clj
@@ -10,35 +10,36 @@

 (def server-url (second *command-line-args*))

-(defn absolute-url [relativeUrl]
+(defn absolute-url-for [relativeUrl]
   (clojure.string/join [server-url relativeUrl]))

-(defn get-url [relativeUrl]
-  (client/get (absolute-url relativeUrl)))
+(defn get-json [relative-url-template & url-params]
+  (let [relative-url (apply format relative-url-template url-params)
+        response (client/get (absolute-url-for relative-url))]
+    (j/parse-string (:body response) true)))

-; /jobStatus.json
+
+;; /jobStatus.json

 (defn parse-build-info [jsonResp]
-  (let [buildInfo (get (first jsonResp) "building_info")
-        buildStartTime (tc/to-long (tf/parse (get buildInfo "build_building_date")))
-        buildEndTime (tc/to-long (tf/parse (get buildInfo "build_completed_date")))
-        result (get buildInfo "result")
+  (let [buildInfo (:building_info (first jsonResp))
+        buildStartTime (tc/to-long (tf/parse (:build_building_date buildInfo)))
+        buildEndTime (tc/to-long (tf/parse (:build_completed_date buildInfo)))
+        result (:result buildInfo)
         outcome (if (= "Passed" result) "pass" "fail")]
     {:start buildStartTime
      :end buildEndTime
      :outcome outcome}))

 (defn build-for [{jobId :jobId}]
-  (let [buildUrl (format "/jobStatus.json?pipelineName=&stageName=&jobId=%s" jobId)
-        buildResp (get-url buildUrl)
-        build (j/parse-string (:body buildResp))]
+  (let [build (get-json "/jobStatus.json?pipelineName=&stageName=&jobId=%s" jobId)]
     (parse-build-info build)))

 (defn job-data-for-instance [jobInstance]
   (assoc jobInstance :build (build-for jobInstance)))

-; /api/stages/%pipeline/%stage/history
+;; /api/stages/%pipeline/%stage/history

 (defn job-instances-for-stage-instance [{pipelineRun :pipeline_counter
                                          stageRun :counter
@@ -51,16 +52,14 @@
        jobs))

 (defn job-instances-for-stage [{stage :stage pipeline :pipeline}]
-  (let [stageHistoryUrl (format "/api/stages/%s/%s/history" pipeline stage)
-        stageHistoryResp (get-url stageHistoryUrl)
-        stageHistory (j/parse-string (:body stageHistoryResp) true)
+  (let [stageHistory (get-json "/api/stages/%s/%s/history" pipeline stage)
         stageInstances (:stages stageHistory)]
     (map #(assoc % :stageName stage :pipelineName pipeline)
          (apply concat
-                (map #(job-instances-for-stage-instance %) stageInstances)))))
+                (map job-instances-for-stage-instance stageInstances)))))

-; /api/config/pipeline_groups
+;; /api/config/pipeline_groups

 (defn stages-for-pipeline [pipeline]
   (let [pipelineName (:name pipeline)
@@ -70,15 +69,13 @@
          stages)))

 (defn stages-for-pipeline-group [pipelineGroupName]
-    (let [pipelineGroupsUrl "/api/config/pipeline_groups"
-          pipelineGroupsResp (get-url pipelineGroupsUrl)
-          pipelineGroups (j/parse-string (:body pipelineGroupsResp) true)
+    (let [pipelineGroups (get-json "/api/config/pipeline_groups")
           pipelineGroup (first (filter #(= pipelineGroupName (:name %)) pipelineGroups))
           pipelines (:pipelines pipelineGroup)]
       (apply concat
              (map stages-for-pipeline pipelines))))

-; upload
+;; upload

 (defn make-build-instance [{jobName :jobName stageName :stageName pipelineName :pipelineName
                             stageRun :stageRun pipelineRun :pipelineRun


Add attribution to calculate-optimal-position code

--- src/re_com/popover.cljs
+++ src/re_com/popover.cljs
@@ -74,7 +74,9 @@

 (defn calculate-optimal-position
-  "Calculate the optimal :position value that results in the least amount of clipping by the screen edges"
+  "Calculate the optimal :position value that results in the least amount of clipping by the screen edges
+  Taken from: https://github.com/Lambda-X/cljs-repl-web/blob/0.3.1/src/cljs/cljs_repl_web/views/utils.cljs#L52
+  Thanks to @richiardiandrea and @tomek for this code"
   [[x y]]
   (let [w (.-innerWidth   js/window) ;; Width/height of the browser window viewport including, if rendered, the vertical scrollbar
         h (.-innerHeight  js/window)


updated test runner

updated test runner

--- cljx/plongeur-cljs/test/all/test_runner.cljs
+++ cljx/plongeur-cljs/test/all/test_runner.cljs
@@ -4,7 +4,8 @@
             [kierros.model-test]
             [kierros.util-test]
             [plongeur.model-test]
-            [plongeur.sigma-driver-test]
+            [plongeur.sigma-test]
+            [plongeur.view-test]
             [cljs.test :refer-macros [run-tests]]))

 ; Run both builds simultaneously!
@@ -17,6 +18,6 @@
            'kierros.util-test

            'plongeur.model-test
-           'plongeur.sigma-driver-test
-
+           'plongeur.sigma-test
+           'plongeur.view-test
            )


add comment to upgrade sample to chaining macro

--- test/lambdacd_artifacts/sample_pipeline.clj
+++ test/lambdacd_artifacts/sample_pipeline.clj
@@ -19,6 +19,7 @@
 (defn produce-output [args ctx]
   (shell/bash ctx (:cwd args) "lein test2junit"))

+;; TODO: upgrade to chaining-macro after release (#39)
 (defn some-build-step [args ctx]
     (step-support/chain args ctx
       (produce-output)


no image for blog post

no image for blog post

--- src/pc/views/blog/we_made_precursor_for_teams.clj
+++ src/pc/views/blog/we_made_precursor_for_teams.clj
@@ -11,7 +11,6 @@
   {:title "We made Precursor for teams."
    :blurb "We want users to know we're not going anywhere. Precursor for Teams will help us ensure your work is private and stays secure. "
    :author "Danny"
-   :image (external-cdn-path "/blog/ideas-are-made-with-precursor/lobanovskiy-placeholder.gif")
    :body
    (list
     [:article


Fix character serialization

Fix character serialization

--- src/robinson/update.clj
+++ src/robinson/update.clj
@@ -24,6 +24,7 @@
             clojure.pprint
             clojure.core.memoize
             clojure.edn
+            clojure.walk
             [clojure.data.json :as json]
             clj-tiny-astar.path
             [clojure.core.async :as async]
@@ -2602,8 +2603,13 @@
                    (let [version (slurp "VERSION")
                          userid  (slurp "config/.userid")
                          url     (format "https://aaron-santos.com:3000/saves/%s" userid)
-                         body    (json/write-str (-> (get state :world)
-                                                     (assoc :version version)))]
+                         body    (as-> (get state :world) world
+                                       (assoc world :version version)
+                                       (clojure.walk/postwalk (fn [v] (if (char? v)
+                                                                        (str v)
+                                                                        v))
+                                                               world)
+                                       (json/write-str world))]
                      (http/post url
                        {:body body
                         :content-type :json})))


Fix fruit dropping

Fix fruit dropping

--- src/robinson/update.clj
+++ src/robinson/update.clj
@@ -2110,10 +2110,9 @@
                                                            (get (get-cell state x y) :type))))
                                         (adjacent-xys x y))]
                     (info "dropping fruit" item "at [" x y "]" adj-xys)
-                    state
-                    #_(if (seq adj-xys)
+                    (if (seq adj-xys)
                       ;; drop the fruit into the cell
-                      (apply conj-cell-items state (dg/rand-nth adj-xys) item)
+                      (apply conj-cell-items state (conj (dg/rand-nth adj-xys) item))
                       state))
                   state)
                 ;; update fire


use cached joins instead of recalculating

--- dada2-core/src/test/clojure/org/dada2/test_join_model.clj
+++ dada2-core/src/test/clojure/org/dada2/test_join_model.clj
@@ -147,7 +147,8 @@
 		   i rhs-pk-key rhs-fk-key lhs-fk-keys rhs join-fn join-pk joined-model]
   (let [fk (rhs-fk-key rhs)
 	lhses (lhses-get lhs-indeces i fk)
-	old-joins2 (mapcat (fn [lhs] (derive-joins old-rhs-indeces lhs-fk-keys lhs join-fn)) lhses)
+	;;old-joins2 (mapcat (fn [lhs] (derive-joins old-rhs-indeces lhs-fk-keys lhs join-fn)) lhses)
+	old-joins2 (vals old-joins)
 	new-rhs-indeces (rhs-dissoc old-rhs-indeces i rhs-pk-key fk rhs)
 	new-joins2 (mapcat (fn [lhs] (derive-joins new-rhs-indeces lhs-fk-keys lhs join-fn)) lhses)
 	joins (remove (fn [i] (contains? (apply hash-set new-joins2) i)) old-joins2)


more price test refactoring cljs

more price test refactoring cljs

--- test-cljs/complico/test/prices.cljs
+++ test-cljs/complico/test/prices.cljs
@@ -2,7 +2,7 @@
   (:require-macros [cemerick.cljs.test
                     :refer (are is deftest with-test run-tests testing test-var)])
   (:use-macros
-   [dommy.macros :only [sel]])
+   [dommy.macros :only [sel sel1]])
   (:require
    [complico.prices :as prices]
    [complico.dom-helper :as dom-helper]
@@ -46,29 +46,25 @@
 (defn confirm-text-remains [actual-text expected-text]
   (is (= actual-text expected-text)))

-(defn dom-with-price []
-  (hipo/create [:body [:div [:div "£0"]]]))
+(defn complex-dom-with-price []
+  (hipo/create [:body [:div [:div#with-price "£0"]]]))

-(deftest replace-price-in-dom-should-correctly-replace-price
-  (let [root-elem (dom-with-price)]
-    (prices/replace-prices-in-dom! root-elem)
-    (-> root-elem
-        (.-lastChild)
-        (.-lastChild)
-        (dom-helper/get-text-from-node)
-        (confirm-text-was-set-to "£XXX"))))
+(deftest replace-price-in-complex-dom-should-find-and-replace-price
+  (-> (complex-dom-with-price)
+    (prices/replace-prices-in-dom!)
+    (sel1 "#with-price")
+    (dom-helper/get-text-from-node)
+    (confirm-text-was-set-to "£XXX")))

-(deftest replace-price-in-dom-should-not-overwrite-html-on-empty-text-nodes
-  (let [root-elem (hipo/create
-          [:body
-            [:div "   "
-              [:div "£0"]]])]
-    (prices/replace-prices-in-dom! root-elem)
-    (-> root-elem
-        (.-lastChild)
-        (.-lastChild)
-        (dom-helper/get-text-from-node)
-        (confirm-text-was-set-to "£XXX"))))
+(defn dom-with-price-but-higher-text-node []
+  (hipo/create [:body [:div "   " [:div#with-price "£0"]]]))
+
+(deftest replace-price-in-dom-should-not-overwrite-innerhtml-on-higher-empty-text-nodes
+  (-> (dom-with-price-but-higher-text-node)
+    (prices/replace-prices-in-dom!)
+    (sel1 "#with-price")
+    (dom-helper/get-text-from-node)
+    (confirm-text-was-set-to "£XXX")))

 (deftest convert-price-should-select-from-conversion-function-list-using-price-value-as-list-index-with-modulus
   (def mock-price-conversion-funcs [(fn [_ _] "0") (fn [_ _] "1") (fn [_ _] "2")])


Add more tests around sync offset date for Go.cd

--- test/buildviz/go/sync_jobs_test.clj
+++ test/buildviz/go/sync_jobs_test.clj
@@ -180,9 +180,38 @@
                                    (a-stage-run 42 "1" "Passed"
                                                 (a-job-run "AlphaJob"
                                                            (- (tc/to-long beginning-of-2016)
+                                                              2))
+                                                (a-job-run "BetaJob"
+                                                           (+ (tc/to-long beginning-of-2016)
+                                                              9001))))
+                  (provide-buildviz-and-capture-puts store))
+        (with-out-str (sut/sync-stages (url/url "http://gocd:8513")
+                                       (url/url "http://buildviz:8010")
+                                       beginning-of-2016 nil nil)))
+      (is (empty? @store))))
+
+  (testing "should sync stage of pipeline that's after the sync date offset"
+    (let [store (atom [])]
+      (fake/with-fake-routes-in-isolation
+        (serve-up (a-config (a-pipeline-group "Development"
+                                              (a-pipeline "Build"
+                                                          (a-stage "DoStuff")
+                                                          (a-stage "SomeMore"))))
+                  (a-short-history "Build" "DoStuff"
+                                   (a-stage-run 42 "1" "Passed"
+                                                (a-job-run "AlphaJob"
+                                                           (- (tc/to-long beginning-of-2016)
                                                               2))))
-                  (provide-buildviz-and-capture-puts store))
-        (with-out-str (sut/sync-stages (url/url "http://gocd:8513")
-                                       (url/url "http://buildviz:8010")
-                                       beginning-of-2016 nil nil)))
-      (is (empty? @store)))))
+                  (a-short-history "Build" "SomeMore"
+                                   (a-stage-run 42 "1" "Passed"
+                                                (a-job-run "SomeJob"
+                                                           (tc/to-long beginning-of-2016))))
+                  (a-pipeline-run "Build" 42)
+                  (a-builds-properties "Build" 42 "SomeMore" "1" "SomeJob" {})
+                  (a-file-list "Build" 42 "SomeMore" "1" "SomeJob")
+                  (provide-buildviz-and-capture-puts store))
+        (with-out-str (sut/sync-stages (url/url "http://gocd:8513")
+                                       (url/url "http://buildviz:8010")
+                                       beginning-of-2016 nil nil)))
+      (is (= ["/builds/Build%20SomeMore/42%201"]
+             (map first @store))))))


Five new tests: test-format-date-time[1-5]

--- test/clj_calendar/calendar_test.clj
+++ test/clj_calendar/calendar_test.clj
@@ -191,3 +191,38 @@
             (is (= "2000-02-01 10:20"  (format-date-using-desired-format calendar "yyyy-MM-dd hh:mm")))
             (is (= "2000-02-01 10:20:30"  (format-date-using-desired-format calendar "yyyy-MM-dd hh:mm:ss"))))))

+(deftest test-format-date-time-1
+    "Check the function clj-calendar.calendar.calendar/format-date-time"
+    (testing "the function clj-calendar.calendar.calendar/format-date-time"
+        (let [calendar (get-calendar)]
+            (.set calendar 2000 01 01 10 20 30)
+            (is (= "2000-02-01 10:20:30" (format-date-time calendar))))))
+
+(deftest test-format-date-time-2
+    "Check the function clj-calendar.calendar.calendar/format-date-time"
+    (testing "the function clj-calendar.calendar.calendar/format-date-time"
+        (let [calendar (get-calendar)]
+            (.set calendar 2000 00 01 10 20 30)
+            (is (= "2000-01-01 10:20:30" (format-date-time calendar))))))
+
+(deftest test-format-date-time-3
+    "Check the function clj-calendar.calendar.calendar/format-date-time"
+    (testing "the function clj-calendar.calendar.calendar/format-date-time"
+        (let [calendar (get-calendar)]
+            (.set calendar 2000 00 31 10 20 30)
+            (is (= "2000-01-31 10:20:30" (format-date-time calendar))))))
+
+(deftest test-format-date-time-4
+    "Check the function clj-calendar.calendar.calendar/format-date-time"
+    (testing "the function clj-calendar.calendar.calendar/format-date-time"
+        (let [calendar (get-calendar)]
+            (.set calendar 2000 11 31 10 20 30)
+            (is (= "2000-12-31 10:20:30" (format-date-time calendar))))))
+
+(deftest test-format-date-time-5
+    "Check the function clj-calendar.calendar.calendar/format-date-time"
+    (testing "the function clj-calendar.calendar.calendar/format-date-time"
+        (let [calendar (get-calendar)]
+            (.set calendar 2000 00 01 00 00 00)
+            (is (= "2000-01-01 00:00:00" (format-date-time calendar))))))
+


Self require tests with cljc files needs more investigation

--- test/cljs/replumb/require_test.cljs
+++ test/cljs/replumb/require_test.cljs
@@ -506,12 +506,15 @@

 ;; see "loop" section here: http://blog.fikesfarm.com/posts/2015-12-18-clojurescript-macro-tower-and-loop.html
 ;; but it does not work in JS ClojureScript
+;; AR - note that Node.js version 0.12.7 behaves differently locally and on
+;; Jenkins. This is the reason of the two different error messages.
 (h/read-eval-call-test e/*target-opts*
   ["(ns my.namespace (:require [foo.bar.self]))"]
   (let [error (unwrap-result @_res_)]
     (is (not (success? @_res_)) (str _msg_ "should not succeed"))
     (is (valid-eval-error? error) (str _msg_ "should be an instance of js/Error"))
-    (is (re-find #"Maximum call stack size exceeded" (extract-message error)) (str _msg_ "should have correct error message"))))
+    (is (or (re-find #"Maximum call stack size exceeded" (extract-message error))
+            (re-find #"No such macros namespace" (extract-message error))) (str _msg_ "should have correct error message"))))

 ;; AR - The following writes on the filesystem
 (when (and e/*write-file-fn* e/*delete-file-fn*)


exit properly from cmdline

exit properly from cmdline

--- src/gh_waiting_room/github_tasks.clj
+++ src/gh_waiting_room/github_tasks.clj
@@ -12,7 +12,12 @@
     (table hooks)
     (println (format "%s rows in set" (count hooks)))))

+(defn abort [msg]
+  (println msg)
+  (System/exit 1))
+
 (defn -main [& [cmd arg]]
   (case cmd
     "hooks" (print-hooks)
-    (println "Usage: lein github [hooks|create-hook|delete-hook]")))+    (abort "Usage: lein github [hooks|create-hook|delete-hook]"))
+  (System/exit 0))