Transition the swagger object through the all the schema building functions

--- src/io/aviso/rook/swagger.clj
+++ src/io/aviso/rook/swagger.clj
@@ -69,25 +69,25 @@

 (defn- simple->swagger-schema
   "Converts a simple (non-object) Schema into an inline Swagger Schema, with keys :type and perhaps :format, etc."
-  [swagger-options schema]
+  [swagger-options swagger-object schema]
   (cond-let
     [data-type-mappings (:data-type-mappings swagger-options)
      data (get data-type-mappings schema)]

     (some? data)
-    data
+    [swagger-object data]

     (instance? EnumSchema schema)
-    {:type :string                                          ; an assumption
-     :enum (unwrap-schema schema)}
+    [swagger-object {:type :string                          ; an assumption
+                     :enum (unwrap-schema schema)}]

     (instance? Maybe schema)
-    (assoc (simple->swagger-schema swagger-options (unwrap-schema schema))
-      :allowEmptyValue true)
+    (let [[swagger-object' swagger-schema] (simple->swagger-schema swagger-options swagger-object (unwrap-schema schema))]
+      [swagger-object' (assoc swagger-schema :allowEmptyValue true)])

     ;; The i.a.r.schema/with-description macro often turns bare classes into an IsInstance
     (instance? IsInstance schema)
-    (recur swagger-options (unwrap-schema schema))
+    (recur swagger-options swagger-object (unwrap-schema schema))

     ;; TODO: arrays

@@ -111,32 +111,31 @@
                       :else
                       (t/track
                         #(format "Describing query parameter `%s'." (name k))
-                        (let [schema-description (simple->swagger-schema swagger-options key-schema)
+                        (let [[swagger-object' schema-description] (simple->swagger-schema swagger-options so key-schema)
                               full-description (assoc schema-description
                                                  :name k
                                                  :in :query
                                                  :required required)]
-                          (update-in so params-key
+                          (update-in swagger-object' params-key
                                      conj full-description)))))]
       (reduce reducer swagger-object schema))
     ; no :query-schema
     swagger-object))

 (defn map->swagger-schema
-  [swagger-options schema]
-  (let [reducer (fn [o [schema-key schema-value]]
-                  (let [[k required?] (reduce-schema-key schema-key)]
-                    (t/track
-                      #(format "Describing key `%s'." (name k))
-                      (let [swagger-schema (simple->swagger-schema swagger-options schema-value)]
-                        (cond-> (assoc-in o [:properties k] swagger-schema)
-                                required? (update-in [:required] conj k))))))]
-    (->>
-      schema
-      remove-any-keys
-      (reduce reducer {:description (or (-> schema meta :description)
-                                        (-> schema meta :doc))})
-      remove-nil-vals)))
+  [swagger-options swagger-object schema]
+  (let [reducer (fn [[swagger-object' o :as acc] [schema-key schema-value]]
+                  (if (= s/Any schema-value)
+                    acc
+                    (let [[k required?] (reduce-schema-key schema-key)]
+                      (t/track
+                        #(format "Describing key `%s'." (name k))
+                        (let [[swagger-object'2 swagger-schema] (simple->swagger-schema swagger-options swagger-object' schema-value)]
+                          [swagger-object'2 (cond-> (assoc-in o [:properties k] swagger-schema)
+                                                    required? (update-in [:required] conj k))])))))
+        base (remove-nil-vals {:description (-> (or (-> schema meta :description)
+                                                    (-> schema meta :doc)))})]
+    (reduce reducer [swagger-object base] schema)))

 (defn ->swagger-schema
   "Converts a Prismatic schema to a Swagger schema (or possibly, a \"$ref\" map pointing to a schema). A $ref
@@ -162,8 +161,8 @@
     ;; Missing this stuff?  Make it anonymous.
     (or (nil? schema-name) (nil? schema-ns))
     ;; The challenge here is nested schemas that may have names. Currently that will blow up.
-    [swagger-object {:schema (map->swagger-schema swagger-options schema)}]
-
+    (let [[so' new-schema] (map->swagger-schema swagger-options swagger-object schema)]
+      [so' {:schema new-schema}])

     ;; Avoid forward slash in the swagger name, as that's problematic.
     [swagger-name (str schema-ns \: schema-name)
@@ -173,11 +172,11 @@
     (some? swagger-schema)
     [swagger-object swagger-reference]

-    [new-schema (map->swagger-schema swagger-options schema)
-     swagger-object' (assoc-in swagger-object [:definitions swagger-name] new-schema)]
+    [[swagger-object' new-schema] (map->swagger-schema swagger-options swagger-object schema)
+     swagger-object'2 (assoc-in swagger-object' [:definitions swagger-name] new-schema)]

     :else
-    [swagger-object' swagger-reference]))
+    [swagger-object'2 swagger-reference]))

 (defn default-body-params-injector
   "Uses the :body-schema metadata to identify the body params."


Add ability to define target-version with keyword

--- src/leiningen/droid/utils.clj
+++ src/leiningen/droid/utils.clj
@@ -180,10 +180,22 @@

 (defn proj [] (read-project "sample/project.clj"))

+(defn sdk-version-number [kw-or-number]
+  (if (keyword? kw-or-number)
+    (case kw-or-number
+      :froyo       8
+      :gingerbread 10
+      :honeycomb   13
+      :ics         15
+      :jelly-bean  17
+      (abort "Unknown Android SDK version: " kw-or-number))
+    kw-or-number))
+
 (defn get-sdk-platform-path
   "Returns a version-specific path to the Android platform tools."
   [sdk-root version]
-  (str (file sdk-root "platforms" (str "android-" version))))
+  (str (file sdk-root "platforms" (str "android-"
+                                       (sdk-version-number version)))))

 (defn get-sdk-android-jar
   "Returns a version-specific path to the `android.jar` SDK file."
@@ -193,7 +205,8 @@
 (defn get-sdk-google-api-path
   "Returns a version-specific path to the Google SDK directory."
   [sdk-root version]
-  (str (file sdk-root "add-ons" (str "addon-google_apis-google-" version))))
+  (str (file sdk-root "add-ons" (str "addon-google_apis-google-"
+                                     (sdk-version-number version)))))

 (defn get-sdk-google-api-jars
   "Returns a version-specific paths to all Google SDK jars."


remove options not applicable to boot-sass

--- src/leiningen/new/tenzing.clj
+++ src/leiningen/new/tenzing.clj
@@ -136,8 +136,6 @@

 (defn development-task-opts [opts]
   (cond-> []
-    (sass? opts) (conj (str "sass   {:line-numbers true
-                                     :source-maps  true}"))
     (less? opts) (conj (str "less   {:source-map  true}"))))

 (defn index-html-head-tags [opts]


Ensure handler, init and destroy passed as vars (fixes #20)

--- src/leiningen/ring/server.clj
+++ src/leiningen/ring/server.clj
@@ -25,6 +25,17 @@
          (if-let [p (System/getenv "SSLPORT")] {:ssl-port p})
          {:environment (or (System/getenv "RING_ENV") "development")}))

+(defn make-vars
+  "Turn the symbols in an option map into vars. Necessary for reloading."
+  [options keys]
+  (reduce
+   (fn [m k]
+     (if-let [v (m k)]
+       (assoc m k `(var ~v))
+       m))
+   options
+   keys))
+
 (defn server-task
   "Shared logic for server and server-headless tasks."
   [project options]
@@ -33,7 +44,8 @@
                        options)]
     (eval-in-project
      project
-     `(leiningen.ring.run-server/run-server ~options)
+     `(leiningen.ring.run-server/run-server
+       ~(make-vars options [:handler :init :destroy]))
      nil nil
      (load-namespaces
       'leiningen.ring.run-server


CMR-3238: Fixing build issues so it works if the proto repl library is not available.

--- common-lib/src/cmr/common/test/test_check_ext.clj
+++ common-lib/src/cmr/common/test/test_check_ext.clj
@@ -7,19 +7,26 @@
             [com.gfredericks.test.chuck.clojure-test :as chuck]
             [clojure.test.check.properties :as prop]
             [clojure.test]
-            [proto-repl.saved-values :as proto-repl-saved-values]
             [clojure.pprint])
   (:import java.util.Random))
+
+(defn require-proto-repl-saved-values
+  "Tries to require proto repl saved values safely. Does nothing if not available."
+  []
+  (try
+   (require 'proto-repl.saved-values)
+   (catch Throwable _)))

 (defn save-last-failed-values
   "Saves the bindings map captured from the given namespace into the Proto REPL saved values atom so
    it can be displayed like normal saved values."
   [name current-ns bindings-map]
-  (let [saved-values-atom (var-get #'proto-repl-saved-values/saved-values-atom)
-        saved-values {:id (proto-repl-saved-values/guid)
-                      :the-ns current-ns
-                      :values bindings-map}]
-   (swap! saved-values-atom assoc name [saved-values])))
+  (when (find-ns 'proto-repl.saved-values)
+    (let [saved-values-atom (var-get (find-var 'proto-repl.saved-values/saved-values-atom))
+          saved-values {:id (.toString (java.util.UUID/randomUUID))
+                        :the-ns current-ns
+                        :values bindings-map}]
+      (swap! saved-values-atom assoc name [saved-values]))))

 (defn binding-values
   "Macro helper. Takes a binding vector and returns a map of code to quote the binding name to
@@ -56,12 +63,15 @@

   For more details on this code, see http://blog.colinwilliams.name/blog/2015/01/26/alternative-clojure-dot-test-integration-with-test-dot-check/"
   [name tests bindings & body]
-  `(chuck/-testing ~name
-    (fn []
-      (let [final-reports# (atom [])]
-        (qc-and-report-exception ~name final-reports# ~tests ~bindings ~@body)
-        (doseq [r# @final-reports#]
-          (chuck/-report r#))))))
+  `(do
+     (require-proto-repl-saved-values)
+     (chuck/-testing
+      ~name
+      (fn []
+        (let [final-reports# (atom [])]
+          (qc-and-report-exception ~name final-reports# ~tests ~bindings ~@body)
+          (doseq [r# @final-reports#]
+            (chuck/-report r#)))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; DEPRECATED


Update comment.

Update comment.

--- src/cavm/h2.clj
+++ src/cavm/h2.clj
@@ -266,8 +266,7 @@
    FOREIGN KEY (probemaps_id) REFERENCES `probemaps` (`id`) ON DELETE CASCADE,
    `probe` VARCHAR(1000) NOT NULL)"])

-; XXX CASCADE might perform badly, since h2 keeps the entire delete transaction
-; in memory. Might need to do this incrementally in application code.
+; XXX CASCADE might perform badly. Might need to do this incrementally in application code.
 (def probemap-positions-table
   ["CREATE TABLE IF NOT EXISTS `probemap_positions` (
    `probemaps_id` INT NOT NULL,


with thanks to putnam who already did this

--- src/cljs/org/broadinstitute/firecloud_ui/page/billing_management.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/billing_management.cljs
@@ -33,8 +33,8 @@
                             :onClick #(swap! state assoc :foo "bar")}]))
          :data (:projects @state)
          :->row (fn [item]
-                  [item
-                   "Member"])}]))
+                  [(item "projectName")
+                  (item "role")])}]))
    :component-did-mount
    (fn [{:keys [this]}]
      (react/call :load-data this))


Act on @otfrom's comments

Act on @otfrom's comments

--- src-cljs/kixi/hecuba/tabs/hierarchy/property_details.cljs
+++ src-cljs/kixi/hecuba/tabs/hierarchy/property_details.cljs
@@ -220,7 +220,7 @@
              ;; is being opened in the browser instead of being downloaded. Should we go through the API
              ;; or just straight to s3?
              (when (or public? editable)
-               (let [[_ _ _ _ _ _ file_name] (str/split uri #"/")]
+               (let [file_name (last (str/split uri #"/"))]
                  (when (and uri file_name) ;; Don't display invalid links
                    [:tr
                     [:td.col-sm-4
@@ -244,7 +244,7 @@
   (om/component
    (html
     (let [{:keys [public? uri]}   cursor
-          [_ _ _ _ _ _ file_name] (str/split uri #"/")]
+          file_name (last (str/split uri #"/"))]
       [:div.col-md-12 {:style {:padding-top "10px"}}
        [:div.panel.panel-default
         [:div.panel-body


properly fix browser when used as replacement for main

object was covered but not string

--- src/main/shadow/build/npm.clj
+++ src/main/shadow/build/npm.clj
@@ -61,9 +61,13 @@
                 (cond->
                   (string? browser)
                   (assoc :browser browser)
+
+                  ;; browser can point to a string and to an object
+                  ;; since object has an entirely different meaning
+                  ;; don't use it as a main
                   (map? browser)
-                  (assoc :browser-overrides browser)))
-            ]
+                  (-> (assoc :browser-overrides browser)
+                      (update :package-json dissoc "browser"))))]

         (swap! index-ref assoc-in [:package-json-cache file] {:content content
                                                               :last-modified last-modified})
@@ -101,8 +105,6 @@
         (reduced path)))
     nil
     extensions))
-
-

 (defn find-package* [{:keys [node-modules-dir] :as npm} package-name]
   ;; this intentionally only checks
@@ -745,7 +747,7 @@
      ;; so use the first thing that exists
      ;; FIXME: if a build ever needs to configure these we can't use the shared npm reference
      :extensions [".js" ".json"]
-     :main-keys [#_#_"module" "jsnext:main" "main"]
+     :main-keys [#_#_"module" "jsnext:main" "browser" "main"]
      }))

 (defn stop [{:keys [babel] :as npm}]


Specify split by time, not position.

Specify split by time, not position.

--- src/african_polyphony_and_polyrhythm/talk.clj
+++ src/african_polyphony_and_polyrhythm/talk.clj
@@ -25,17 +25,16 @@
 (defmethod live/play-note :clap2 [_]
   ((sample "samples/select-click.wav")))

-(defn split [n fraction]
+(defn split [t fraction]
   (fn [notes]
-    (let [note (nth notes n)
-          first-note (-> note (update-in [:duration] * fraction))
+    (let [before? #(-> % :time (< t))
+          before (->> notes (take-while before?))
+          [note & after] (->> notes (drop-while before?))
+          first-note (assoc note :duration fraction)
           second-note (-> note
-                          (update-in [:duration] * (- 1 fraction))
-                          (update-in [:time] + (:duration first-note)))]
-      (concat
-        (take n notes)
-        [first-note second-note]
-        (drop (inc n) notes)))))
+                          (update-in [:duration] - fraction)
+                          (update-in [:time] + fraction))]
+      (concat before [first-note second-note] after))))

 (definst akadinda [freq 440 vol 0.5]
   (-> (sin-osc freq)
@@ -62,9 +61,9 @@
 (def tete
   (part
     (phrase [2 1/2 3/2] (repeat 0))
-    (split 0 1/8)
-    (comp (split 1 1/7) (split 0 1/8))
-    (comp (split 2 1/6) (split 1 1/7) (split 0 1/8))))
+    (split 0 1/4)
+    (comp (split 1/4 1/4) (split 0 1/4))
+    (comp (split 2/4 1/4) (split 1/4 1/4) (split 0 1/4))))

 (def ta
   (part
@@ -75,7 +74,7 @@
 (def ha
   (part
     (phrase [1/2 3 1/2] (cons nil (repeat 2)))
-    (comp (split 4 1/2) (split 2 1/6) (split 0 1/4))))
+    (comp (split 3/2 1/4) (split 1/2 1/4) (split 0 1/4))))

 (def tulule
   (part
@@ -85,9 +84,9 @@
 (def bongo
   (part
     (phrase [3/2 3/4 7/4] (cons nil (repeat 4)))
-    (split 2 5/7)
-    (comp (split 1 1/3) (split 2 5/7))
-    (comp (split 4 1/2) (split 1 1/3) (split 2 5/7))))
+    (split 9/4 5/4)
+    (comp (split 3/2 1/4) (split 9/4 5/4))
+    (comp (split 14/4 1/4) (split 3/2 1/4) (split 9/4 5/4))))

 (defn up [notes]
   (->> notes


added base field types for demo table

added base field types for demo table

--- src/metabase/driver/crate.clj
+++ src/metabase/driver/crate.clj
@@ -4,10 +4,16 @@
             (korma [core :as k]))
   (:import (clojure.lang Named)))

+(defn- column->base-type
+  "Map of Postgres column types -> Field base types.
+   Add more mappings here as you come across them."
+  [_ column-type]
+  ({:int           :IntegerField
+    :text          :TextField} column-type))
+
 (defrecord CrateDriver []
   Named
   (getName [_] "Crate"))
-

 (defn- crate-spec
   [{:keys [host port]
@@ -31,7 +37,8 @@
 (def CrateISQLDriverMixin
   "Implementations of `ISQLDriver` methods for `CrateDriver`."
   (merge (sql/ISQLDriverDefaultsMixin)
-         {:connection-details->spec  connection-details->spec}))
+         {:connection-details->spec  connection-details->spec
+          :column->base-type         column->base-type}))

 (extend CrateDriver
   driver/IDriver


Cleanup coordinator.

Cleanup coordinator.

--- src/onyx/peer/coordinator.clj
+++ src/onyx/peer/coordinator.clj
@@ -173,6 +173,7 @@
              :checkpointing? checkpoint?
              :checkpoint-epoch (if checkpoint? (m/epoch messenger) (:checkpoint-epoch state))
              :offering? true
+             :scheduled? false
              :write-version next-write-version
              :barrier-opts {:completed? (:sealing? state)
                             :checkpoint? checkpoint?}
@@ -216,19 +217,11 @@
           ;; Continue offering barriers until success
           (offer-barriers state)

-          completed?
-          (do
-           (LockSupport/parkNanos coordinator-max-sleep-ns)
-           state)
-
-          sealing?
-          (if (checkpointing? state status)
-            (do
-             (LockSupport/parkNanos coordinator-max-sleep-ns)
-             state)
-            (complete-job state))
-
-          (or (not= (m/replica-version messenger) (:replica-version status))
+          (and sealing? (not (checkpointing? state status)))
+          (complete-job state)
+
+          (or completed? sealing?
+              (not= (m/replica-version messenger) (:replica-version status))
               (not= (m/epoch messenger) (:min-epoch status)))
           (do
            (LockSupport/parkNanos coordinator-max-sleep-ns)
@@ -236,10 +229,10 @@

           (:drained? status)
           ;; emit final completion barrier
-          (periodic-barrier (assoc state :sealing? true :scheduled? false))
+          (periodic-barrier (assoc state :sealing? true))

           (and scheduled? (> (System/nanoTime) next-barrier-time))
-          (periodic-barrier (assoc state :sealing? false :scheduled? false))
+          (periodic-barrier state)

           (and (not scheduled?)
                (not (checkpointing? state status)))


Helper refactoring

Helper refactoring

--- src/hyjinks.clj
+++ src/hyjinks.clj
@@ -4,18 +4,18 @@

 ;; General helpers

-(defn unnamed [x] (if (instance? clojure.lang.Named x) (name x) x))
+(defn only-if [pred f] (fn [x] (if (pred x) (f x) x)))
+
+(def unnamed (only-if (partial instance? clojure.lang.Named) name))

 (defn str-join [& items] (apply str (map unnamed (flatten items))))

-(defn html-escape [s]
-	(if-not (string? s) s
-		(escape (unnamed s) {
-			\< "<"
-			\> ">"
-			\& "&"
-			\" """
-			\' "'"})))
+(def html-escape (only-if string? #(escape % {
+	\< "<"
+	\> ">"
+	\& "&"
+	\" """
+	\' "'"})))

 (defmacro defrecord-ifn [& record-parts]
 	(let [parted-record (partition-by #(= % 'clojure.lang.IFn) record-parts)


Exit on close

Exit on close

--- desktop/src/nightweb_desktop/window.clj
+++ desktop/src/nightweb_desktop/window.clj
@@ -1,8 +1,7 @@
 (ns nightweb-desktop.window
   (:require [splendid.jfx :as jfx])
   (:import (javafx.scene.layout VBox Priority)
-           (javafx.scene.control TabPane Tab)
-           javafx.collections.ListChangeListener)
+           (javafx.scene.control TabPane Tab))
   (:use [nightweb-desktop.browser :only [create-tab]]))

 (defn add-tab
@@ -26,7 +25,7 @@
       (.add (.getTabs tab-bar) plus-tab)
       (jfx/defhandler :onSelectionChanged plus-tab (add-tab tab-bar))
       (.addListener (.getTabs tab-bar)
-                    (reify ListChangeListener
+                    (reify javafx.collections.ListChangeListener
                       (onChanged [this change]
                         (let [tabs (butlast (.getTabs tab-bar))]
                           (doseq [tab tabs]
@@ -36,4 +35,8 @@
       (.setWidth jfx/primary-stage 1024)
       (.setHeight jfx/primary-stage 768)
       (jfx/add window [tab-bar])
-      (jfx/show window))))
+      (jfx/show window)
+      (.setOnCloseRequest jfx/primary-stage
+                          (reify javafx.event.EventHandler
+                            (handle [this event]
+                              (java.lang.System/exit 0)))))))


Fixes #12

Fixes #12

--- src/statuses/views/common.clj
+++ src/statuses/views/common.clj
@@ -10,6 +10,7 @@
                (include-css "/statuses/css/bootstrap.css")
                (include-css "/statuses/css/bootstrap-responsive.css")
                (include-css "/statuses/css/statuses.css")
+               [:link {:href "/statuses/updates.atom" :rel "alternate" :title "innoQ Statuses Feed" :type "application/atom+xml"}]
                [:style "body { padding-top: 60px; }"]]
               [:body
                (list


We now need to load the cert for clojars [IMMUTANT-75]

--- modules/core/src/main/clojure/immutant/runtime/bootstrap.clj
+++ modules/core/src/main/clojure/immutant/runtime/bootstrap.clj
@@ -145,6 +145,7 @@
 to gracefully handle missing dependencies."
   [project]
   (when project
+    (project/load-certificates project)
     (try
       (classpath/resolve-dependencies :dependencies project)
       (catch DependencyResolutionException e


fix insert-half-tile

fix insert-half-tile

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

--- plugins/SlideExplorer2/src/slide_explorer/image.clj
+++ plugins/SlideExplorer2/src/slide_explorer/image.clj
@@ -33,6 +33,12 @@

 ; ImageProcessor-related utilities

+(defn clone
+  "Duplicates and ImageProcessor."
+  [processor]
+  (when processor
+    (.duplicate processor)))
+
 (defn insert-image!
   "Inserts one ImageProcessor into another."
   [proc-host proc-guest x-host y-host]
@@ -151,7 +157,7 @@

 (defn insert-half-tile
   [tile [left? upper?] mosaic]
-  (let [dest (black-processor-like mosaic)]
+  (let [dest (or (clone mosaic) (black-processor-like tile))]
     (insert-half-tile! dest tile [left? upper?])))

 ;; stats
@@ -283,7 +289,7 @@
 (defn gaussian-blur
   "Applys a gaussian blur to ImageProcessor, with given radius."
   [processor radius]
-  (let [new-proc (.duplicate processor)]
+  (let [new-proc (clone processor)]
     (.blurGaussian (GaussianBlur.) new-proc radius radius 0.0002)
     new-proc))

@@ -312,7 +318,7 @@
 (defn multiply
   "Multiply an image processor by a factor."
   [processor factor]
-  (doto (.duplicate processor)
+  (doto (clone processor)
     (.multiply factor)))

 (def add-processors


Use ->> for consitency.

Use ->> for consitency.

--- src/overtunes/songs/row_row_row_your_boat.clj
+++ src/overtunes/songs/row_row_row_your_boat.clj
@@ -9,7 +9,7 @@

 (defn bpm [per-minute] #(-> % (/ per-minute) (* 60) (* 1000)))
 (defn after [timing beats] #(-> % (+ beats) timing))
-(defn syncopate [timing durations] #(-> (sum-n durations %) timing))
+(defn syncopate [timing durations] #(->> % (sum-n durations) timing))
 (defn from [timing start] #(-> % timing (+ start)))

 (def pitches [0 0 0 1 2, 2 1 2 3 4, 7 7 7 4 4 4 2 2 2 0 0 0, 4 3 2 1 0])


fixing typo

fixing typo

--- src/text_stream/templates.clj
+++ src/text_stream/templates.clj
@@ -40,7 +40,7 @@
       [:li [:a#titleset.right {:href "#"} "Set Title"]]]]
     [:pre#stream.content
      [:span.cursor "Type Here"]]
-    (page/include-js "/utils.js" "/make-stream.js")]))x
+    (page/include-js "/utils.js" "/make-stream.js")]))

 (def page-count 15)


Populate thumbnails on update-image endpoint resource.

--- src/uxbox/frontend/images.clj
+++ src/uxbox/frontend/images.clj
@@ -150,6 +150,8 @@
                        :type :update-image
                        :user user)]
     (->> (sv/novelty message)
+         (p/map populate-thumbnails)
+         (p/map populate-urls)
          (p/map #(http/ok (rsp %))))))

 ;; --- Delete Image


CMR-1867 Document functions as attribute values.

--- umm-spec-lib/src/cmr/umm_spec/umm_to_xml_mappings/dsl.clj
+++ umm-spec-lib/src/cmr/umm_spec/umm_to_xml_mappings/dsl.clj
@@ -14,7 +14,9 @@
   generators that specify the content of the element.

   Note that first inner map without a ::type will be treated as attributes for the element. The
-  attributes map is treated as a map of attribute names to content generators for each attribute.
+  attributes map is treated as a map of attribute names to content generators for each attribute. A
+  zero-argument function may be supplied for an attribute value which will be called to generate the
+  actual output value.

   ## String


Bumps version to 1.43.2-SNAPSHOT

Bumps version to 1.43.2-SNAPSHOT

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.43.1"
+(defproject cook "1.43.2-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


process-filter-sort for every language

process-filter-sort for every language

--- hsm.batch/src/hsm/batch.clj
+++ hsm.batch/src/hsm/batch.clj
@@ -7,8 +7,10 @@
     [cascalog.logic.ops :as c]
     [cheshire.core :refer :all]
     [hsm.batch.core :as b.core]
+    [cascalog.more-taps :as c.more]
   )(:gen-class))

+(defn integer[s] (Integer/parseInt s))

 (defn load-json
   [f]
@@ -23,7 +25,7 @@
   (<- [?id ?watchers ?language ?proj]
     (source :> ?proj ?idx ?watchers ?language ?full)
     (fill-s :< ?idx :> ?id)
-    (> ?watchers 50)
+    (> ?watchers 5)
     ; (fill-s :< ?languagex :> ?language)
     ))

@@ -33,28 +35,65 @@

 (defn top-projects
   [out-tap query top-n]
-  (?- out-tap
+  (?- out-tap
     (top-obj query ["?watchers"] top-n)))

+(defn final-set
+  [data-source]
+  (<- [?id ?watch ?lang ?name]
+    (data-source :> ?id ?w ?lang ?name)
+    (integer ?w :> ?watch)))
+
+(defn language-filtered
+  [lang data-source]
+  (<- [?id ?watch ?lang ?name]
+    (data-source :> ?id ?watch ?lang ?name)
+    (= lang ?lang)))
+
+(deffilterfn is-lang
+  "NULL Languages exported as 54abc by either Hadoop or Cassandra.
+  So filter here by checking if text contains 54"
+  [l]
+  (not (.contains l "54")))
+
+(defn languages
+  [data-source]
+  (<- [?lang]
+    (data-source :> ?id ?watch ?lang ?name)
+    (:distinct true)
+    (is-lang ?lang)))
+
 (defn process
-  [files cutoff top-n]
-  (let [sorting ["?watchers"]]
-    (info files)))
+  [file cutoff top-n output]
+  (info "Processing" file)
+  (let [sorting ["?watch"]
+        data-source (c.more/lfs-delimited file)
+        max-items 1000
+        all-languages (first (??- (languages (final-set data-source))))]
+    (info all-languages)
+    (?- (stdout)
+      (top-obj (final-set data-source) sorting 1000))
+    (doseq [[lang] all-languages]
+      (info lang)
+      (?- (lfs-textline (str output "lang/" lang))
+        (top-obj (language-filtered lang (final-set data-source)) ["?watch"] max-items)))))

 (defn extract
-  [f cutoff]
+  [f cutoff output]
+  (warn "EXTRACT " f cutoff)
   (let [part (last (vec (.split f "/")))
         objects (b.core/parsevaluate (load-json f))
         objects (if (> cutoff 0) (subvec (vec objects) 0 cutoff) objects)]
-    (?- (lfs-textline (str ".run/" part "/") :sinkmode :replace)
+    (?- (lfs-textline (str output part "/") :sinkmode :replace)
        (all-projects objects))))

 (defn -main
   "I don't do a whole lot ... yet."
-  [mode f cutoff & args]
-  (info mode f cutoff args)
-  (let [cut (Integer/parseInt cutoff)]
+  [mode output cutoff & args]
+  (info mode cutoff args)
+  (let [files args
+    cut (Integer/parseInt cutoff)]
   (condp = mode
-    "e" (extract f cut)
-    "g" (process (vec args) 0 cut)
-    )))
+    "e" (mapv #(extract % cut output) files)
+    "g" (process (first files) 0 cut output))
+  (info "DONE!")))


remove println

remove println

--- priv/ui/src/cljs/holiday_ping_ui/channels/subs.cljs
+++ priv/ui/src/cljs/holiday_ping_ui/channels/subs.cljs
@@ -29,7 +29,6 @@
 (re-frame/reg-sub
  :slack-channels
  (fn [db [_ slack-channel]]
-   (println "lala" slack-channel)
    (->> (get-in slack-channel [:configuration :channels])
         (filter #(string/starts-with? % "#"))
         (string/join " "))))
@@ -37,7 +36,6 @@
 (re-frame/reg-sub
  :slack-users
  (fn [db [_ slack-channel]]
-   (println "LOLO" slack-channel)
    (->> (get-in slack-channel [:configuration :channels])
         (filter #(string/starts-with? % "@"))
         (string/join " "))))


Oops, _actually_ fix for JDK7

Oops, _actually_ fix for JDK7

--- test/caesium/binding_test.clj
+++ test/caesium/binding_test.clj
@@ -3,7 +3,7 @@
             [clojure.test :refer [deftest is]])
   (:import [caesium.binding Sodium]
            [java.lang.annotation Annotation]
-           [java.lang.reflect Method Parameter Type AnnotatedElement]
+           [java.lang.reflect Method Type AnnotatedElement]
            [jnr.ffi.annotations In Out Pinned LongLong]
            [jnr.ffi.byref LongLongByReference]
            [java.nio ByteBuffer]


pull paren up

pull paren up

--- test/clj_kafka/test/utils.clj
+++ test/clj_kafka/test/utils.clj
@@ -71,5 +71,4 @@
          (try ~@body
               (finally (do (.shutdown kafka#)
                            (.shutdown zk#)
-                           (FileUtils/deleteDirectory (file (tmp-dir))))))))
-  )
+                           (FileUtils/deleteDirectory (file (tmp-dir)))))))))


Add reframe tests

Add reframe tests

--- test/cljs/russyll/runner.cljs
+++ test/cljs/russyll/runner.cljs
@@ -3,10 +3,11 @@
               [usertest_test]
               [syllab-test]
               [orphoep_test]
-              [text-test]))
-
+              [text-test]
+              [russyll.re-frame-test]))

 (doo-tests 'usertest_test
            'syllab-test
            'orphoep_test
-           'text-test)
+           'text-test
+           'russyll.re-frame-test)


Add test for multiple terms unified with literal

Refs #117.

--- test/desdemona/query_test.clj
+++ test/desdemona/query_test.clj
@@ -103,6 +103,13 @@
                  (#'q/dsl->logic '(= (:ip x) "10.0.0.1" "10.0.0.1"))))
     (is (thrown? IllegalArgumentException
                  (#'q/dsl->logic '(= (:ip x) "10.0.0.1" "10.0.0.2")))))
+  (testing "multiple terms unified with a literal"
+    (is (= '(clojure.core.logic/all
+             (clojure.core.logic/featurec x {:ip "10.0.0.1"})
+             (clojure.core.logic/featurec y {:ip "10.0.0.1"}))
+           (#'q/dsl->logic '(= (:ip x) (:ip y) "10.0.0.1"))
+           (#'q/dsl->logic '(= (:ip x) "10.0.0.1" (:ip y)))
+           (#'q/dsl->logic '(= "10.0.0.1" (:ip x) (:ip y))))))
   (testing "linking events"
     (with-fake-gensym
       (is (= '(clojure.core.logic/fresh [fake-gensym-1]


No longer clutter test output with validation exceptions

--- test/onyx/validation_test.clj
+++ test/onyx/validation_test.clj
@@ -9,17 +9,13 @@

 (deftest validation-errors
   (let [id (java.util.UUID/randomUUID)
+        _ (timbre/merge-config! {:appenders {:println {:enabled? false}}
+                                 :level :error})
         config (load-config)
-        env-config
-        (assoc (:env-config config)
-               :onyx/tenancy-id id
-               :onyx.log/config {:appenders {:standard-out {:enabled? false}
-                                             :spit {:enabled? false}}})
         peer-config
         (assoc (:peer-config config)
                :onyx/tenancy-id id
                :onyx.peer/job-scheduler :onyx.job-scheduler/balanced)
-        env (onyx.api/start-env env-config)
         workflow
         [[:in-bootstrapped :inc]
          [:inc :out]]
@@ -222,9 +218,7 @@
       (is (thrown? Exception (onyx.api/submit-job peer-config {:catalog correct-catalog
                                                                :workflow correct-workflow
                                                                :lifecycles invalid-lifecycles
-                                                               :task-scheduler :onyx.task-scheduler/balanced}))))
-
-    (onyx.api/shutdown-env env)))
+                                                               :task-scheduler :onyx.task-scheduler/balanced}))))))

 (deftest map-set-workflow


Stringify _id in get-user.

Stringify _id in get-user.

When the session is stored in a cookie it must be serializeable.
ObjectId is not.

--- src/cadence/model.clj
+++ src/cadence/model.clj
@@ -61,8 +61,12 @@
                                              {:username criteria}
                                              criteria)
                                            fields)]
-     (assoc user-map :roles (namespace-and-keywordize-roles
-                              (:roles user-map)))))
+     (let [overwrite-fields {:roles (namespace-and-keywordize-roles
+                                                    (:roles user-map))
+                             ;; The ObjectId type is not serializeable so just
+                             ;; make it a string.
+                             :_id (str (:_id user-map))}]
+       (merge user-map overwrite-fields))))
   ([criteria] (get-user criteria [])))

 (defn add-roles-to-users


[Closes #214] Get var from symbol

[Closes #214] Get var from symbol

--- priv/clojure/core.clj
+++ priv/clojure/core.clj
@@ -1601,9 +1601,10 @@

 ;;;;;;;;; var stuff

-(defn set!
+(defmacro set!
   [x val]
-  (clj_core/set!.e x val))
+  (assert-args (symbol? x) "a symbol as its first argument")
+  `(clj_core/set!.e (var ~x) ~val))

 (defmacro ^{:private true} assert-args
   [& pairs]


packets.clj: Remove excess field from function

--- src/packets.clj
+++ src/packets.clj
@@ -211,7 +211,7 @@
            fields)))

 ;; Create the const PACKET_ID fields
-(defn const-packet-id [{name :name id :id}]
+(defn const-packet-id [{id :id}]
   (format "    const PACKET_ID: i32 = %s;" id))

 ;; Given the fields of a packet, return a string containing functions that


:tada: Introduce async (batched) shapes changes commit event.

--- frontend/src/uxbox/main/data/workspace.cljs
+++ frontend/src/uxbox/main/data/workspace.cljs
@@ -117,11 +117,7 @@

 (defn interrupt? [e] (= e :interrupt))

-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Websockets Events
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; --- Initialize WebSocket
+;; --- Declarations

 (declare fetch-users)
 (declare handle-who)
@@ -129,6 +125,15 @@
 (declare handle-pointer-send)
 (declare handle-page-snapshot)
 (declare shapes-changes-commited)
+(declare commit-shapes-changes)
+(declare async-commit-shapes-changes)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Websockets Events
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; --- Initialize WebSocket
+

 (s/def ::type keyword?)
 (s/def ::message
@@ -293,7 +298,7 @@
   [file-id page-id]
   (s/assert ::us/uuid file-id)
   (s/assert ::us/uuid page-id)
-  (ptk/reify ::initialized
+  (ptk/reify ::finalize
     ptk/UpdateEvent
     (update [_ state]
       (dissoc state
@@ -309,7 +314,25 @@
             data (get-in state [:pages-data page-id])]
         (assoc state
                :workspace-data data
-               :workspace-page page)))))
+               :workspace-page page)))
+
+    ptk/WatchEvent
+    (watch [_ state stream]
+      (let [stoper (rx/filter #(or (ptk/type? ::finalize %)
+                                   (ptk/type? ::initialize-page %))
+                              stream)
+            notifier (->> stream
+                          (rx/filter (ptk/type? ::async-commit-shapes-changes))
+                          (rx/debounce 500))]
+        (->> stream
+             (rx/filter (ptk/type? ::async-commit-shapes-changes))
+             (rx/map deref)
+             (rx/mapcat identity)
+             (rx/buffer-until notifier)
+             (rx/map vec)
+             (rx/map commit-shapes-changes)
+             (rx/take-until stoper)
+             (rx/finalize #(prn "FINALIZE" %)))))))

 ;; --- Fetch Workspace Users

@@ -588,7 +611,6 @@
         (update-in $ [:workspace-data :shapes] conj id))
       (assoc-in $ [:workspace-data :shapes-by-id id] shape))))

-(declare commit-shapes-changes)
 (declare select-shape)
 (declare recalculate-shape-canvas-relation)

@@ -741,7 +763,7 @@
     ptk/WatchEvent
     (watch [_ state stream]
       (let [change (::tmp-change state)]
-        (rx/of (commit-shapes-changes [change])
+        (rx/of (async-commit-shapes-changes [change])
                #(dissoc state ::tmp-change))))))

 ;; --- Update Selected Shapes attrs
@@ -1006,7 +1028,6 @@
   [operations]
   (s/assert ::cp/operations operations)
   (ptk/reify ::commit-shapes-changes
-    ;; Commits the just performed changes to root pages-data
     ptk/UpdateEvent
     (update [_ state]
       (let [pid (get-in state [:workspace-local :page-id])
@@ -1021,6 +1042,13 @@
                     :operations operations}]
         (->> (rp/mutation :update-project-page params)
              (rx/map shapes-changes-commited))))))
+
+(defn async-commit-shapes-changes
+  [operations]
+  (s/assert ::cp/operations operations)
+  (ptk/reify ::async-commit-shapes-changes
+    cljs.core/IDeref
+    (-deref [_] operations)))

 (s/def ::shapes-changes-commited
   (s/keys :req-un [::page-id ::version ::cp/operations]))


Fix blob type case

Fix blob type case

It looks like there is a typo in full->normal in the cases. The extra slash in the case "id3/frame.type/blob" results in this error when calling it with a tag of the blob type

> Execution error (IllegalArgumentException) at id3/full->normal$fn (id3.clj:77).
> No matching clause: :id3.frame.type/blob

--- src/id3.clj
+++ src/id3.clj
@@ -77,7 +77,7 @@
 				:id3.frame.type/user-text (m/map-vals :id3.frame/content (m/index-by :id3.frame/description frames))
 				:id3.frame.type/user-url (m/map-vals :id3.frame/content (m/index-by :id3.frame/description frames))
 				:id3.frame.type/picture (mapv #(select-keys % [:id3.frame/picture-type :id3.frame/mime-type :id3.frame/bytes]) frames)
-				:id3/frame.type/blob (mapv :id3.frame/bytes frames))))))
+				:id3.frame.type/blob (mapv :id3.frame/bytes frames))))))

 (defn normal->full [version tag] {
 	::magic-number "ID3"


add event trigger for placed advancements

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -570,22 +570,18 @@
         (update-all-ice state side)
         (clear-run-register! state))))

-
 (defn add-prop
   ([state side card key n] (add-prop state side card key n nil))
   ([state side card key n {:keys [placed] :as args}]
-   (let [updated-card (if
-                        (has? card :subtype "Virus")
-                        (assoc card :added-virus-counter true)
-                        card
-                        )]
+   (let [updated-card (if (has? card :subtype "Virus")
+                        (assoc card :added-virus-counter true) card)]
      (update! state side (update-in updated-card [key] #(+ (or % 0) n)))
      (if (= key :advance-counter)
        (do (when (and (ice? updated-card) (rezzed? updated-card)) (update-ice-strength state side updated-card))
-           (when (not placed)
-             (trigger-event state side :advance (get-card state updated-card))))
-       (trigger-event state side :counter-added (get-card state updated-card)))
-     )))
+           (if (not placed)
+             (trigger-event state side :advance (get-card state updated-card))
+             (trigger-event state side :advancement-placed (get-card state updated-card))))
+       (trigger-event state side :counter-added (get-card state updated-card))))))

 (defn set-prop [state side card & args]
   (update! state side (apply assoc (cons card args))))


Fix uniqueness. The unique flag should not be removed from cards when creating the decks at game start.

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -648,7 +648,7 @@
 (defn create-deck [deck]
   (shuffle (mapcat #(map (fn [card]
                            (let [c (assoc card :cid (make-cid))
-                                 c (dissoc c :setname :text :_id :influence :number :uniqueness :influencelimit
+                                 c (dissoc c :setname :text :_id :influence :number :influencelimit
                                            :faction :factioncost)]
                              (if-let [init (:init (card-def c))] (merge c init) c)))
                          (repeat (:qty %) (:card %)))


Update query to include type category-drugs

Including the matching type allows for the autocomplete analyzer to
work properly, which matches edge ngrams.

Edge ngrams are a sequence of characters that form word parts starting
at the word edges, and can be used for matching search input to results.

--- src/cljs/app/app.cljs
+++ src/cljs/app/app.cljs
@@ -72,7 +72,8 @@
   (let [out (chan)]
     (go (while true
       (let [[url search-text] (<! in)
-            response (<! (http/get url {:query-params {"q" search-text}}))]
+            response (<! (http/get url {:query-params
+                                         {"q" (str "category-drugs:" search-text)}}))]
         (>! out (vector search-text response)))))
     out))


(PDB-1031) Reproduce the fact paths constraint issue

This patch creates a unit test that recreates the following error:

update or delete on table "fact_paths" violates foreign key constraint "fact_values_path_id_fk" on table "fact_values"

[rlb@puppetlabs.com: remove demonstration output; instrument
 delete-pending-path-id-orphans! instead of delete-facts!, which is no
 longer called by replace-facts!; remove unused with-pg-test-db]

--- test/com/puppetlabs/puppetdb/test/command.clj
+++ test/com/puppetlabs/puppetdb/test/command.clj
@@ -972,6 +972,141 @@
           (is (true? @first-message?))
           (is (true? @second-message?)))))))

+(defn thread-id []
+  (.getId (Thread/currentThread)))
+
+(deftest fact-path-update-race
+  ;; Simulates two update commands being processed for two different
+  ;; machines at the same time.  Before we lifted fact paths into
+  ;; facts, the race tested here could result in a constraint
+  ;; violation when the two updates left behind an orphaned row.
+  (let [certname-1 "some_certname1"
+        certname-2 "some_certname2"
+        ;; facts for server 1, has the same "mytimestamp" value as the
+        ;; facts for server 2
+        facts-1a {:name certname-1
+                  :environment nil
+                  :values {"domain" "mydomain1.com"
+                           "operatingsystem" "Debian"
+                           "mytimestamp" "1"}}
+        facts-2a {:name certname-2
+                  :environment nil
+                  :values {"domain" "mydomain2.com"
+                           "operatingsystem" "Debian"
+                           "mytimestamp" "1"}}
+
+        ;; same facts as before, but now certname-1 has a different
+        ;; fact value for mytimestamp (this will force a new fact_value
+        ;; that is only used for certname-1
+        facts-1b {:name certname-1
+                  :environment nil
+                  :values {"domain" "mydomain1.com"
+                           "operatingsystem" "Debian"
+                           "mytimestamp" "1b"}}
+
+        ;; with this, certname-1 and certname-2 now have their own
+        ;; fact_value for mytimestamp that is different from the
+        ;; original mytimestamp that they originally shared
+        facts-2b {:name certname-2
+                  :environment nil
+                  :values {"domain" "mydomain2.com"
+                           "operatingsystem" "Debian"
+                           "mytimestamp" "2b"}}
+
+        ;; this fact set will disassociate mytimestamp from the facts
+        ;; associated to certname-1, it will do the same thing for
+        ;; certname-2
+        facts-1c {:name certname-1
+                  :environment nil
+                  :values {"domain" "mydomain1.com"
+                           "operatingsystem" "Debian"}}
+        facts-2c {:name certname-2
+                  :environment nil
+                  :values {"domain" "mydomain2.com"
+                           "operatingsystem" "Debian"}}
+        command-1b   {:command (command-names :replace-facts)
+                      :version 3
+                      :payload facts-1b}
+        command-2b   {:command (command-names :replace-facts)
+                      :version 3
+                      :payload facts-2b}
+        command-1c   {:command (command-names :replace-facts)
+                      :version 3
+                      :payload facts-1c}
+        command-2c   {:command (command-names :replace-facts)
+                      :version 3
+                      :payload facts-2c}
+
+        ;; Wait for two threads to countdown before proceeding
+        latch (java.util.concurrent.CountDownLatch. 2)
+
+        ;; I'm modifying delete-pending-path-id-orphans! so that I can
+        ;; coordinate access between the two threads, I'm storing the
+        ;; reference to the original delete-pending-path-id-orphans!
+        ;; here, so that I can delegate to it once I'm done
+        ;; coordinating
+        storage-delete-pending-path-id-orphans!
+        scf-store/delete-pending-path-id-orphans!]
+
+    (sql/transaction
+     (scf-store/add-certname! certname-1)
+     (scf-store/add-certname! certname-2)
+     (scf-store/add-facts! {:name certname-1
+                            :values (:values facts-1a)
+                            :timestamp (now)
+                            :environment nil
+                            :producer-timestamp nil})
+     (scf-store/add-facts! {:name certname-2
+                            :values (:values facts-2a)
+                            :timestamp (now)
+                            :environment nil
+                            :producer-timestamp nil}))
+
+    ;; At this point, there will be 4 fact_value rows, 1 for
+    ;; mytimestamp, 1 for the operatingsystem, 2 for domain
+    (with-redefs [scf-store/delete-pending-path-id-orphans!
+                  (fn [& args]
+                    ;; Once this has been called, it will countdown
+                    ;; the latch and block
+                    (.countDown latch)
+                    ;; After the second command has been executed and
+                    ;; it has decremented the latch, the await will no
+                    ;; longer block and both threads will begin
+                    ;; running again
+                    (.await latch)
+                    ;; Execute the normal delete-pending-path-id-orphans!
+                    ;; function (unchanged)
+                    (apply storage-delete-pending-path-id-orphans! args))]
+      (let [first-message? (atom false)
+            second-message? (atom false)
+            fut-1 (future
+                    (test-msg-handler command-1b publish discard-dir
+                      (reset! first-message? true)))
+            fut-2 (future
+                    (test-msg-handler command-2b publish discard-dir
+                      (reset! second-message? true)))]
+        ;; The two commands are being submitted in future, ensure they
+        ;; have both completed before proceeding
+        @fut-2
+        @fut-1
+        ;; At this point there are 6 fact values, the original
+        ;; mytimestamp, the two new mytimestamps, operating system and
+        ;; the two domains
+        (is (true? @first-message?))
+        (is (true? @second-message?))
+        ;; Submit another factset that does NOT include mytimestamp,
+        ;; this disassociates certname-1's fact_value (which is 1b)
+        (test-msg-handler command-1c publish discard-dir
+          (reset! first-message? true))
+        ;; Do the same thing with certname-2. Since the reference to 1b
+        ;; and 2b has been removed, mytimestamp's path is no longer
+        ;; connected to any fact values. The original mytimestamp value
+        ;; of 1 is still in the table. It's now attempting to delete
+        ;; that fact path, when the mytimestamp 1 value is still in
+        ;; there.
+        (test-msg-handler command-2c publish discard-dir
+          (is (not (extract-error-message publish))))))))
+
 (deftest concurrent-catalog-updates
   (testing "Should allow only one replace catalogs update for a given cert at a time"
     (let [test-catalog (get-in catalogs [:empty])


changes to vcs-url parsing

changes to vcs-url parsing

--- frontend/utils/vcs_url.cljs
+++ frontend/utils/vcs_url.cljs
@@ -2,7 +2,7 @@
   (:require [clojure.string :as string]))

 (defn project-name [vcs-url]
-  (subs vcs-url 19 (count vcs-url)))
+  (last (re-find #"^https?://[^/]+/(.*)" vcs-url)))

 ;; slashes aren't allowed in github org/user names or project names
 (defn org-name [vcs-url]


GAWB-1790: Entity names in moniter tab now show correctly

--- src/cljs/main/broadfcui/page/workspace/monitor/submission_details.cljs
+++ src/cljs/main/broadfcui/page/workspace/monitor/submission_details.cljs
@@ -95,7 +95,7 @@
    :render-workflow-details
    (fn [{:keys [props]} workflowId]
      (let [workflows (:workflows props)
-           workflowName (get-in workflows [0 "workflowEntity" "entityName"])]
+           workflowName (get-in (filterv #(= (get-in % ["workflowId"]) workflowId) workflows) [0 "workflowEntity" "entityName"])]
        [:div {}
         [:div {:style {:marginBottom "1rem" :fontSize "1.1rem"}}
          [comps/Breadcrumbs {:crumbs


map/pmap and print out final error ratio at the end

--- src/babel/francais/qa.clj
+++ src/babel/francais/qa.clj
@@ -23,6 +23,7 @@

 (defn read-expressions [& [this-many]]
   (let [this-many (if this-many (Integer. this-many))
+        map (if this-many map pmap)
         results (db/exec-raw [(str "SELECT target.serialized::text AS target,target.surface
                                       FROM expression AS target
                                      WHERE target.language=?
@@ -62,7 +63,11 @@
                   (log/info (str "parse results: " (count parsed)))))))
           (if this-many
             (take this-many (shuffle results))
-            results)))))
+            results)))
+    (log/info (str "final error ratio:" @total-errors " out of "
+                   @total "; error rate=" (string/replace (str (/ @total-errors (+ 0.0 @total)) "00")
+                                                          #"^(....).*" "$1")))))
+


Change name of debugger middleware

Change name of debugger middleware

--- src/datemo/routes.clj
+++ src/datemo/routes.clj
@@ -85,15 +85,16 @@
   (GET "/documents/:uuid-str" [uuid-str] (get-doc uuid-str))
   (route/not-found "Not found"))

-(defn wrap-with-logger [handler]
+(defn wrap-with-debugger [handler]
   (fn [request]
+    ;; (pprint request)
     (prn (str "Request: " (:request-method request) " " (:uri request)))
     (handler request)))

 (def app
   (-> app-routes
       (wrap-json-response)
-      ;; (wrap-with-logger)
+      ;; (wrap-with-debugger)
       (wrap-json-body {:keywords? true})
       (wrap-cors :access-control-allow-origin [#"http://localhost:8080"]
                  :access-control-allow-methods [:get :put :post :delete])


Case-insensitive comparison of the mime types added.

--- src/domino/export.clj
+++ src/domino/export.clj
@@ -39,7 +39,8 @@
 (defn message-mime
   [doc pathname]
   (let [mime (.getMIMEEntity doc)]
-    (let [type (.getContentType mime) sub (.getContentSubType mime)]
+    (let [type (clojure.string/lower-case (.getContentType mime))
+          sub (clojure.string/lower-case (.getContentSubType mime))]
       (with-message [message (notes-headers-map mime)]
         (cond
          (some #(= type %) ["multipart" "message"]) (message-build-multipart mime)


Update cats.monad.maybe

Update cats.monad.maybe

In -mreturn, if v is nil, return #<Nothing>, otherwise #<Just v>.

--- src/cats/monad/maybe.cljc
+++ src/cats/monad/maybe.cljc
@@ -202,7 +202,9 @@

     p/Monad
     (-mreturn [_ v]
-      (just v))
+      (if (nil? v)
+        (nothing)
+        (just v)))
     (-mbind [_ mv f]
       (if (nothing? mv)
         mv


Fix typehint: should be fully qualified

Fix typehint: should be fully qualified

--- src/cheshire/generate.clj
+++ src/cheshire/generate.clj
@@ -35,8 +35,8 @@
        Long (.writeNumber ~jg (long ~obj))
        Double (.writeNumber ~jg (double ~obj))
        Float (.writeNumber ~jg (double ~obj))
-       BigInteger (.writeNumber ~jg ~(with-meta obj {:tag "BigInteger"}))
-       BigDecimal (.writeNumber ~jg ~(with-meta obj {:tag "BigDecimal"}))
+       BigInteger (.writeNumber ~jg ~(with-meta obj {:tag `BigInteger}))
+       BigDecimal (.writeNumber ~jg ~(with-meta obj {:tag `BigDecimal}))
        Ratio (.writeNumber ~jg (double ~obj))
        Short (.writeNumber ~jg (int ~obj))
        Byte (.writeNumber ~jg (int ~obj))


* src/clj/cljs/compiler.clj: rearrange resolve-var to look more like resolve-existing-var. in both return the local binding directly instead of a map with just its name

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -90,7 +90,7 @@
     (let [s (str sym)
           lb (-> env :locals sym)]
       (cond
-       lb {:name (:name lb)}
+       lb lb

        (namespace sym)
        (let [ns (namespace sym)
@@ -127,32 +127,30 @@
   (if (= (namespace sym) "js")
     {:name (js-var sym)}
     (let [s (str sym)
-          lb (-> env :locals sym)
-          nm
-          (cond
-           lb (:name lb)
-
-           (namespace sym)
-           (let [ns (namespace sym)
-                 ns (if (= "clojure.core" ns) "cljs.core" ns)]
-             (symbol (str (resolve-ns-alias env ns) "." (munge (name sym)))))
-
-           (.contains s ".")
-           (munge (let [idx (.indexOf s ".")
-                        prefix (symbol (subs s 0 idx))
-                        suffix (subs s idx)
-                        lb (-> env :locals prefix)]
-                    (if lb
-                      (symbol (str (:name lb) suffix))
-                      sym)))
-
-           :else
-           (munge (symbol (str
-                           (if (core-name? env sym)
-                             'cljs.core
-                             (-> env :ns :name))
-                           "." (munge (name sym))))))]
-      {:name nm})))
+          lb (-> env :locals sym)]
+      (cond
+       lb lb
+
+       (namespace sym)
+       (let [ns (namespace sym)
+             ns (if (= "clojure.core" ns) "cljs.core" ns)]
+         {:name (symbol (str (resolve-ns-alias env ns) "." (munge (name sym))))})
+
+       (.contains s ".")
+       (let [idx (.indexOf s ".")
+             prefix (symbol (subs s 0 idx))
+             suffix (subs s idx)
+             lb (-> env :locals prefix)]
+         (if lb
+           {:name (munge (symbol (str (:name lb) suffix)))}
+           {:name (munge sym)}))
+
+       :else
+       (let [s (str (if (core-name? env sym)
+                      'cljs.core
+                      (-> env :ns :name))
+                    "." (munge (name sym)))]
+         {:name (munge (symbol s))})))))

 (defn- comma-sep [xs]
   (apply str (interpose "," xs)))


Revert "proxy all on 404"

Revert "proxy all on 404"

This reverts commit b44aa6421208a4781b72a2a71e7339465b375555.

--- src/frontend/core.clj
+++ src/frontend/core.clj
@@ -46,11 +46,11 @@
 (def port 3000)

 (def proxy-config
-  ;;NOTE: This proxies everything that the pipeline doesn't serve first.  We
-  ;; didn't do that originally because it masks problems with the fe/be split,
-  ;; but proxy-all eases development for others, so I won't check-in my
-  ;; patterns. -Brandon
-  {:patterns [#"/.*"]
+  {:patterns [#"/"
+              #"/changelog.rss"
+              #"/logout"
+              #"/auth/.*"
+              #"/api/.*"]
    :backends {"dev.circlehost" {:proto "http" :host "circlehost:8080"}
               "prod.circlehost" {:proto "https" :host "circleci.com"}
               "staging.circlehost" {:proto "https" :host "staging.circleci.com"}}})


clarify foreign dep loading with some comments

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -814,12 +814,17 @@
         (emitln "if(!COMPILED) " loaded-libs " = cljs.core.set();"))
       (doseq [lib (remove (set (vals seen)) (distinct (vals libs)))]
         (cond
-          ;; only emit if foreign lib under Node.js
           (ana/foreign-dep? lib)
+          ;; under node.js we load foreign libs globally
           (if (= :nodejs (get-in @env/*compiler* [:options :target]))
             (let [js-index (:js-dependency-index @env/*compiler*)
                   ijs-url  (get-in js-index [(name lib) :url])]
               (emitln "cljs.core.load_file(\"" (util/get-name ijs-url) "\");"))
+            ;; otherwise only include if set in the options to do so,
+            ;; in the browser unnecessary due to the fact that goog.require
+            ;; there works by writing all deps as script tags, this doesn't
+            ;; work in Rhino-like environment where we do a proper goog.require
+            ;; on demand
             (when (get-in @env/*compiler* [:options :require-foreign])
               (emitln "goog.require('" (munge lib) "');")))


Kode for å finne bilder uten data og data uten bilder.

--- src/clj/movement/util.clj
+++ src/clj/movement/util.clj
@@ -61,6 +61,55 @@
 (def db (d/db conn))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+(defn image-url [name]
+  (str "public/images/" (str/replace (str/lower-case name) " " "-") ".png"))
+
+(defn has-no-image? [m]
+  (if-not (io/resource (image-url m))
+    true
+    false))
+
+(defn url->name [url]
+  (let [name (-> url
+                 (str/split (re-pattern ".png"))
+                 (first)
+                 (str/replace "-" " ")
+                 (str/split (re-pattern " ")))
+        name (map #(str/capitalize %) name)
+        name (-> name
+                 (interleave (cycle " "))
+                 (drop-last)
+                 (str/join))]
+    name))
+
+(defn has-no-data? [url]
+  (let [name (url->name url)
+        x (d/q '[:find ?e
+                 :in $ ?name
+                 :where
+                 [?e :movement/name ?name]]
+               db
+               name)]
+    (empty? x)))
+
+(defn find-no-image-movements []
+  (let [movements (flatten (seq (d/q '[:find ?name
+                                       :where
+                                       [_ :movement/name ?name]]
+                                     db)))
+        no-image-movements (filter #(has-no-image? %) movements)]
+    [(count no-image-movements) no-image-movements]))
+
+(defn find-no-data-images []
+  (let [f (io/file "resources/public/images")
+        images (for [file (file-seq f)] (.getName file))
+        images (drop 2 images)
+        no-data-images (filter #(has-no-data? %) images)]
+    [(count no-data-images) no-data-images]))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defn create-equipment-session [name n]
   (let [r (d/q '[:find (pull ?m [*])
                  :in $ ?name


refactor

refactor

--- src/clj/scrabble/core.clj
+++ src/clj/scrabble/core.clj
@@ -29,10 +29,7 @@

 (def ALL-WORDS
   ;; TODO: should this be a constant instead?
-  (->> (:english const/DICT-FILES)
-       slurp
-       (str/split-lines)
-       (clean-words)))
+  (load-words (:english const/DICT-FILES)))

 (defn char-value
   "Return the value of the given char"


Function to parse boolean values

Function to parse boolean values

--- src/clj_mrazik/config.clj
+++ src/clj_mrazik/config.clj
@@ -7,7 +7,7 @@
 ;  http://www.eclipse.org/legal/epl-v10.html
 ;
 ;  Contributors:
-;      Pavel Tisnovsky
+;      Pavel Tisnovsky
 ;

 (ns clj-mrazik.config)
@@ -25,6 +25,12 @@
     "Parse the given string as a float number."
     [string]
     (java.lang.Float/parseFloat string))
+
+(defn parse-boolean
+    "Parse the given string as a boolean value."
+    [^String string]
+    (or (= string "true")
+        (= string "True")))

 (defn parse-hh-mm-time-as-minutes
     "Parse the given string that has to have format 'HH:mm' and returns
@@ -56,13 +62,18 @@
         (update-in [:geolocation :latitude]  parse-float)
         (update-in [:geolocation :longitude] parse-float)))

+(defn update-modules-configuration
+    "Update configuration for all modules (enabled/disabled)."
+    [configuration]
+
 (defn load-configuration
     "Load configuration from the provided INI file."
     [ini-file-name]
     (-> (clojure-ini/read-ini ini-file-name :keywordize? true)
         update-server-configuration
         update-bot-configuration
-        update-geolocation-configuration))
+        update-geolocation-configuration
+        update-modules-configuration))

 (defn print-configuration
     "Print actual configuration to the output."


Add more examples from cfbt book

Add more examples from cfbt book

--- src/clojure/cfbt/ch04.clj
+++ src/clojure/cfbt/ch04.clj
@@ -70,3 +70,22 @@
 (take 3 [1 2 3 4 5 6 7 8 9 10]) ;; (1 2 3)

 (drop 3 [1 2 3 4 5 6 7 8 9 10]) ;; (4 5 6 7 8 9 10)
+
+(def food-journal
+  [{:month 1 :day 1 :human 5.3 :critter 2.3}
+   {:month 1 :day 2 :human 5.1 :critter 2.0}
+   {:month 2 :day 1 :human 4.9 :critter 2.1}
+   {:month 2 :day 2 :human 5.0 :critter 2.5}
+   {:month 3 :day 1 :human 4.2 :critter 3.3}
+   {:month 3 :day 2 :human 4.0 :critter 3.8}
+   {:month 4 :day 1 :human 3.7 :critter 3.9}
+   {:month 4 :day 2 :human 3.7 :critter 3.6}])
+
+(take-while #(< (:month %) 3) food-journal) ;; ({:month 1, :day 1, :human 5.3, :critter 2.3} {:month 1, :day 2, :human 5.1, :critter 2.0} {:month 2, :day 1, :human 4.9, :critter 2.1} {:month 2, :day 2, :human 5.0, :critter 2.5})
+
+(drop-while #(< (:month %) 3) food-journal) ;; ({:month 3, :day 1, :human 4.2, :critter 3.3} {:month 3, :day 2, :human 4.0, :critter 3.8} {:month 4, :day 1, :human 3.7, :critter 3.9} {:month 4, :day 2, :human 3.7, :critter 3.6})
+
+(take-while #(< (:month %) 4)
+            (drop-while #(< (:month %) 2) food-journal)) ;; ({:month 2, :day 1, :human 4.9, :critter 2.1} {:month 2, :day 2, :human 5.0, :critter 2.5} {:month 3, :day 1, :human 4.2, :critter 3.3} {:month 3, :day 2, :human 4.0, :critter 3.8})
+
+;; Filter and some! (TBC)


Fix docstring placement in list-builder

Fix docstring placement in list-builder

--- src/cognitect/transit.clj
+++ src/cognitect/transit.clj
@@ -240,9 +240,9 @@
     (complete [_ m] (persistent! m))))

 (defn list-builder
-  []
   "Creates an ArrayBuilder that makes Clojure-
    compatible lists."
+  []
   (reify ArrayReader
     (init [_] (transient []))
     (init [_ ^int size] (transient []))


More words

More words

--- src/con_gusto_1/words.clj
+++ src/con_gusto_1/words.clj
@@ -33,6 +33,66 @@
      {:es "me llamo" :nl "ik heet"}
      {:es "¿y tú?" :nl "en jij?"}
      {:es "¿y usted?" :nl "en u?"}
+     {:es "saludos y despedidas" :nl "begroeten en afscheid nemen"}
+     {:es "el saludo" :nl "de begroeting"}
+     {:es "la despedida" :nl "het afscheid"}
+     {:es "otra vez" :nl "nog een keer"}
+     {:es "adiós" :nl "tot ziens"}
+     {:es "buenos días" :nl "goedemorgen"}
+     {:es "el día" :nl "de dag"}
+     {:es "buenas tardes" :nl "goedemiddag"}
+     {:es "la tarde" :nl "de namiddag"}
+     {:es "buenas noches" :nl "goedenavond"}
+     {:es "la noche" :nl "de nacht"}
+     {:es "hasta pronto" :nl "tot snel"}
+     {:es "hasta luego" :nl "tot ziens"}
+     {:es "hasta mañana" :nl "tot morgen"}
+     {:es "o" :nl "of"}
+     {:es "¿Cómo se pronuncia?" :nl "Hoe spreek je het uit?"}
+     {:es "pronunciar" :nl "uitspreken"}
+     {:es "estos nombres" :nl "deze namen"}
+     {:es "leer" :nl "lezen"}
+     {:es "luego" :nl "dan, daarna"}
+     {:es "completar" :nl "aanvullen"}
+     {:es "la playa" :nl "het strand"}
+     {:es "la información" :nl "de informatie"}
+     {:es "la organización" :nl "de organisatie"}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
+     {:es "" :nl ""}
     ]
    7
     [
@@ -590,8 +650,5 @@
      {:es "va a visitar" :nl "u gaat bezoeken"}
      {:es "el preparativo" :nl "de voorbereiding"}
     ]
-   10
-    [
-    ]
   }
 )


bad indent causing my OCD to kick in

bad indent causing my OCD to kick in

--- src/crawler/extractor.clj
+++ src/crawler/extractor.clj
@@ -24,8 +24,8 @@

 (def *page-sim-thresh* 0.9)

-(def *visited*       (atom
-                      (set [])))  ; set of visited documents
+(def *visited* (atom (set [])))  ; set of visited documents
+
 (def *url-documents* (atom {}))   ; url -> body map

 (defn add-xpath


Fix broken logging to route to function mapping

--- src/io/aviso/rook.clj
+++ src/io/aviso/rook.clj
@@ -71,7 +71,7 @@
               ;; It would be nice if there was a way to qualify the path for when we are nested
               ;; inside a Compojure context, but we'd need the request to do that.
               (l/debugf "Mapping %s to %s"
-                        (utils/summarize-method-and-uri route-method name) route-path f)
+                        (utils/summarize-method-and-uri route-method route-path) f)
               [route-method (clout/route-compile route-path) f full-meta]))
        (remove nil?)
        doall))


change field-spec-of to force 'type' and allow entity-or-type as argument

This change is needed for references.  When using get-reference, grab, grab-in
you pass the entity and those functions use 'field-spec-of' to get the correct document.
'field-spec-of' returned nil because entity was being sent not type.

--- src/karras/entity.clj
+++ src/karras/entity.clj
@@ -139,10 +139,11 @@
     (class entity-or-type)))

 (defn field-spec-of
-  "Given a type and one or more keys,
+  "Given a type or entity  and one or more keys,
    returns the  field spec for the last key."
-  [type & keys]
-  (let [field-type (or (reduce (fn [t k]
+  [entity-or-type & keys]
+  (let [type (get-type entity-or-type)
+        field-type (or (reduce (fn [t k]
                                  (-> t entity-spec :fields k :type))
                                type
                                (butlast keys))


No longer need terrible "samestate?" function

--- src/laogai/lights.clj
+++ src/laogai/lights.clj
@@ -30,25 +30,15 @@
   (every? true?
           (map #(:on (state %)) lights)))

-(defn samestate?
-  "Returns boolean value based on whether a given map of params
-   is equal to the current state of the light"
-  [params light]
-  (let [params (dissoc params :transitiontime)
-        lstate (state light)]
-    (every? true?
-            (map #(= (params %)
-                     (lstate %))
-                 (keys params)))))
-
 (defn set!
   "For each light in the configuration, set the state from params"
   [params]
   (doseq [light lights]
     ;; Only set a new state if it doesn't match the previously set state
     ;; This will allow for manual changes to lights that won't be overridden
-    (when-not (samestate? params @last-set)
+    (when-not (= params @last-set)
       (reset! last-set params)
+      (prn "Setting light " light " to: " params)
       (http/put (str base "lights/" light "/state")
                 {:form-params params
                  :content-type :json}))))


[#9759] App freezes if tap on digital keyboard after "Cancel" on Send Transaction screen

Signed-off-by: Andrey Shovkoplyas <b713972e59b8e606e23253c4a13e948139fea4d1@gmail.com>

--- src/status_im/ui/components/bottom_panel/views.cljs
+++ src/status_im/ui/components/bottom_panel/views.cljs
@@ -6,6 +6,7 @@

 (defn hide-panel-anim
   [bottom-anim-value alpha-value window-height]
+  (react/dismiss-keyboard!)
   (anim/start
    (anim/parallel
     [(anim/spring bottom-anim-value {:toValue         (- window-height)


nice indentation

nice indentation

--- src/metabase/driver/generic_sql/query_processor.clj
+++ src/metabase/driver/generic_sql/query_processor.clj
@@ -201,8 +201,8 @@
   (println "SOURCE TABLE: " source_table)
   (log/debug
    "\n********************"
-   "\nQUERY ->" (with-out-str (clojure.pprint/pprint query))
+   "\nQUERY ->"      (with-out-str (clojure.pprint/pprint query))
    "\nKORMA FORM ->" (with-out-str (clojure.pprint/pprint `(select (table-id->korma-entity ~source_table) ~@forms)))
-   "\nSQL ->" (eval `(let [entity# (table-id->korma-entity ~source_table)]
-                       (sql-only (select entity# ~@forms))))
+   "\nSQL ->"        (eval `(let [entity# (table-id->korma-entity ~source_table)]
+                              (sql-only (select entity# ~@forms))))
    "\n********************\n"))


immutable parser

immutable parser

--- src/modelo/parser.clj
+++ src/modelo/parser.clj
@@ -1,11 +1,19 @@
-(ns modelo.parser)
+(ns modelo.parser
+  (:require [clj-by.example :refer [example do-for-example]]))
+
+(def ^:private +examples-enabled+ true)

 (defn mk-parser
   "Create an empty parser."
   []
-  (atom {:const {}
-         :extra {}
-         :compound {}}))
+  {:const {}
+   :extra []
+   :compound {}})
+
+(do-for-example
+ (def ex-parser (atom (mk-parser))))
+
+(declare parse-extra)

 (defn parse
   "Parses an expression `e` with `parser`.
@@ -15,78 +23,163 @@
     - `[:yes <expr>]` if parse is successful
     - `[:no <info-map>]` in case of failure (no parser found)
     - `[:error <info-map>]` in case of error."
-  ([e parser] (if (seq e)
-                (if-let [sparser (get (:compound parser) (first e))]
-                  (sparser e parser)
-                  (reduce (fn [res lparser]
-                            (let [res' (lparser e parser)]
-                              (case (first res')
-                                :no res
-                                :yes (reduce res')
-                                :error (reduce res'))))
-                          [:no {:msg "Cannot parse expression" :expr e}]
-                          (:extra parser)))
+  ([e parser] (if (sequential? e)
+                (if (seq e)
+                  (if-let [sparser (get (:compound parser) (first e))]
+                    (sparser e parser)
+                    (parse-extra e parser))
+                  (parse-extra e parser))
                 ;; consts
                 (if-let [aparser (get (:const parser) e)]
                   (aparser e)
-                  [:error {:msg "No parser for const" :expr e}]))))
+                  [:no {:msg "No parselet for const" :expr e}]))))

-(defn register-const-parser!
-  "Registers in `atom` `parser` as a const parser for `const`."
-  [atom const parser]
-  (swap! atom (fn [p] (if (get (:const p) const)
-                        (throw (ex-info "Const parser already registered."
-                                        {:const const}))
-                        (update p :const
-                                (fn [ps] (assoc ps const parser)))))))
+(defn parse-extra [e parser]
+  (reduce (fn [res eparser]
+            (let [res' (eparser e parser)]
+              (case (first res')
+                :no res
+                :yes (reduced res')
+                :error (reduced res'))))
+          [:no {:msg "Cannot parse expression" :expr e}]
+          (:extra parser)))

-(defn unregister-const-parser!
-  "Unregisters in `atom` the parser for `const`."
-  [atom const]
-  (swap! atom (fn [p] (if (get (:const p) const)
-                        (update p :const
-                                (fn [ps] (dissoc ps const)))
-                        (throw (ex-info "No such const parser registered."
-                                        {:const const}))))))
+(defn check-parse
+  "Parses expression `e` with parser `parser`.
+  Returns the parsed value or raises an exception in case of failure."
+  [e parser]
+  (let [res (parse e parser)]
+    (case (first res)
+      :yes (second res)
+      :no (throw (ex-info "No parselet found for expression." {:expr e :info (second res)}))
+      :error (throw (ex-info "Parse error" {:expr e :error (second res)})))))

-(defn clear-const-parsers!
-  "Unregister in `atom` all const parsers."
-  [atom]
-  (swap! atom #(assoc % :const {})))
+(defn register-const-parselet
+  "Registers in `parser` `parselet` for parsing `const`."
+  [parser const parselet]
+  (if (get (:const parser) const)
+    (throw (ex-info "Const parser already registered."
+                    {:const const}))
+    (update parser :const
+            (fn [ps] (assoc ps const parselet)))))

-(defn register-extra-parser!
-  "Registers in `atom` `parser` as a extra parser."
-  [atom parser]
-  (swap! atom (fn [p] (update p :extra #(conj % parser)))))
+(do-for-example
+ (swap! ex-parser (fn [parser] (register-const-parselet parser 'true (fn [_] [:yes true])))))

-(defn clear-extra-parsers!
-  "Unregister in `atom` all extra parsers."
-  [atom]
-  (swap! atom #(assoc % :extra {})))
+(example
+ (parse 'true @ex-parser) => [:yes true])

-(defn register-compound-parser!
-  "Registers in `atom` `parser` as a compound parser with first element `fst`."
-  [atom fst parser]
-  (swap! atom
-         (fn [p] (update p :compound #(if (get % fst)
-                                        (throw (ex-info "Compound parser already registered."
-                                                        {:first fst}))
-                                        (assoc % fst parser))))))
+(example
+ (parse 'false @ex-parser)
+ => [:no {:msg "No parselet for const", :expr 'false}])

-(defn unregister-compound-parser!
-  "Unregisters in `atom` the compound parser for `fst`."
-  [atom fst]
-  (swap! atom (fn [p] (if (get (:compound p) fst)
-                        (update p :compound
-                                (fn [ps] (dissoc ps fst)))
-                        (throw (ex-info "No such compound parser registered."
-                                        {:first fst}))))))
+(defn unregister-const-parselet
+  "Unregisters in `parser` the parselet for `const`."
+  [parser const]
+  (if (get (:const parser) const)
+    (update parser :const
+            (fn [ps] (dissoc ps const)))
+    (throw (ex-info "No such const parselet registered."
+                    {:const const}))))

+(example
+ (:const (unregister-const-parselet @ex-parser 'true)) => {})

-(defn clear-compound-parsers!
-  "Unregister in `atom` all compound parsers."
-  [atom]
-  (swap! atom #(assoc % :compound {})))
+(defn clear-const-parselets
+  "Unregister in `parser` all const parselets."
+  [parser] (assoc parser :const {}))

+(example
+ (:const (clear-const-parselets @ex-parser)) => {})

+(defn register-extra-parselet
+  "Registers in `parser` `parselet` as a extra parselet."
+  [parser parselet]
+  (update parser :extra #(conj % parselet)))

+(do-for-example
+ (swap! ex-parser
+        (fn [parser] (register-extra-parselet
+                      parser
+                      (fn [v _] (if (and (= (count v) 2)
+                                         (integer? (first v))
+                                         (keyword? (second v)))
+                                  [:yes v]
+                                  [:no {:msg "Not a good pair" :expr v}]))))))
+
+(example
+ (parse [12 :hello] @ex-parser) => [:yes [12 :hello]])
+
+(example
+ (parse [12 'hello] @ex-parser)
+ => [:no {:msg "Not a good pair", :expr [12 'hello]}])
+
+(defn clear-extra-parselets
+  "Unregister in `parser` all extra parserlets."
+  [parser]
+  (assoc parser :extra []))
+
+(defn register-compound-parselet
+  "Registers in `parser` `parselet` as a compound parselet with first element `fst`."
+  [parser fst parselet]
+  (update parser :compound
+          #(if (get % fst)
+             (throw (ex-info "Compound parselet already registered."
+                             {:first fst}))
+             (assoc % fst parselet))))
+
+(do-for-example
+ (swap! ex-parser
+        (fn [parser] (register-compound-parselet
+                      parser 'beep
+                      (fn [v p]
+                        (if (= (count v) 2)
+                          (let [res (parse (second v) p)]
+                            (if (= (first res) :yes)
+                              [:yes {:type :beep :child (second res)}]
+                              [:error (second res)]))
+                          [:error {:msg "Need exactly one argument for :beep."
+                                   :nb-args (dec (count v))}]))))))
+
+(example
+ (parse '(beep [42 :world]) @ex-parser)
+ => [:yes {:type :beep, :child [42 :world]}])
+
+(example
+ (parse '(beep 42) @ex-parser)
+ => [:error {:msg "No parser for const", :expr 42}])
+
+(example
+ (parse '(beep true 42) @ex-parser)
+ => [:error {:msg "Need exactly one argument for :beep.", :nb-args 2}])
+
+(defn unregister-compound-parselet
+  "Unregisters in `parser` the compound parselet for `fst`."
+  [parser fst]
+  (if (get (:compound parser) fst)
+    (update parser :compound
+            (fn [ps] (dissoc ps fst)))
+    (throw (ex-info "No such compound parselet registered."
+                    {:first fst}))))
+
+(example
+ (:compound (unregister-compound-parselet @ex-parser 'beep)) => {})
+
+(defn clear-compound-parselets
+  "Unregister in `parser` all compound parselets."
+  [parser] (assoc parser :compound {}))
+
+(defn clear-parselets
+  "Unregister all parselets in `parser`."
+  [parser]
+  (-> parser
+      (clear-const-parselets)
+      (clear-compound-parselets)
+      (clear-extra-parselets)))
+
+(do-for-example
+ (swap! ex-parser clear-parselets))
+
+(example
+ (= @ex-parser (mk-parser)) => true)
+


Change section headers in cortex.util

Change section headers in cortex.util

--- cortex/src/cortex/util.cljc
+++ cortex/src/cortex/util.cljc
@@ -82,7 +82,7 @@
      (defn rand-gaussian []
        (rand-gaussian* 0 1.0))))

-;;;; Sequences and collections
+;;;; Sequences

 (defn seq-like?
   "Returns true if x ought to be viewed as a sequence. This is a
@@ -109,6 +109,8 @@
   (lazy-seq
     (if-let [ss (seq (filter identity (map seq colls)))]
       (concat (map first ss) (apply interleave-all (map rest ss))))))
+
+;;;; Collections

 (defn map-keys
   "Applies f to each of the keys of a map, returning a new map."


Update styles for header-icon-button

Update styles for header-icon-button

--- src/elfeed_cljsrn/ui.cljs
+++ src/elfeed_cljsrn/ui.cljs
@@ -37,7 +37,8 @@
       [rn/text {:style (:text styles)} label]]]))

 (defn header-icon-button [icon-name props]
-  (let [styles (merge-with merge {:button {:margin 16}
+  (let [styles (merge-with merge {:button {:margin-vertical 16
+                                           :margin-horizontal 12}
                                   :icon {:color (:text palette)}} (:style props))]
     [rn/touchable-opacity {:on-press (:on-press props)}
      [rn/view {:style (:button styles)}


Fix balanced grouping test - accidentally peer count, plus tasks tested were wrong.

--- test/onyx/log/balanced_grouping_generative_test.clj
+++ test/onyx/log/balanced_grouping_generative_test.clj
@@ -243,6 +243,6 @@
        (is (= 4 (count (get (get (:allocations replica) job-1-id) t2))))
        (is (= 3 (count (get (get (:allocations replica) job-1-id) t3))))

-       (is (= 0 (count (get (get (:allocations replica) job-2-id) t1))))
-       (is (= 0 (count (get (get (:allocations replica) job-2-id) t2))))
-       (is (= 1 (count (get (get (:allocations replica) job-2-id) t3))))))))
+       (is (= 0 (count (get (get (:allocations replica) job-2-id) t4))))
+       (is (= 0 (count (get (get (:allocations replica) job-2-id) t5))))
+       (is (= 0 (count (get (get (:allocations replica) job-2-id) t6))))))))


Added function to make the start of a tag

--- src/hiccup.clj
+++ src/hiccup.clj
@@ -8,6 +8,7 @@

 (ns hiccup
   "Efficiently generate HTML from a Clojure data structure."
+  (:use clojure.contrib.def)
   (:use clojure.contrib.java-utils))

 (defn escape-html
@@ -27,7 +28,7 @@
     (not value)   nil
     :otherwise    [(as-str key) (escape-html value)]))

-(defn- make-attrs
+(defn make-attrs
   "Turn a map into a string of HTML attributes, sorted by attribute name."
   [attrs]
   (apply str
@@ -35,14 +36,13 @@
       (if attr
         (str " " attr "=\"" value "\"")))))

-(defn- make-tag
-  "Wrap some content in an HTML tag."
-  [tag attrs content]
-  (str* "<" tag (map-to-attrs attrs) ">"
-          content
-        "</" tag ">"))
+(defvar- re-tag
+  #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?"
+  "Regular expression that parses a CSS-style id and class from a tag name.")

-(defn- make-closed-tag
-  "Make a closed XML tag with no content."
-  [tag attrs]
-  (str* "<" tag (map-to-attrs attrs) " />"))
+(defn make-start-tag
+  "Create the start of a tag, given a tag name with optional CSS-style syntax
+  to denote the id and classes."
+  [tag]
+  (let [[_ tag id classes] (re-matches re-tag (as-str tag))]
+    (str "<" tag (make-attrs {:id id, :class classes}))))


Fix class-set docstring

Fix class-set docstring

--- src/om_tools/dom.cljx
+++ src/om_tools/dom.cljx
@@ -104,6 +104,6 @@
 #+cljs
 (defn class-set [m]
   "Returns a string of keys with truthy values joined together by spaces,
-   or returns nil when no truthy values. Naming comes from React."
+   or returns nil when no truthy values."
   (when-let [ks (->> m (filter val) keys (clojure.core/map name) distinct seq)]
     (str/join " " ks)))


Got the warning arguments round the wrong way

--- src/pedantic/core.clj
+++ src/pedantic/core.clj
@@ -117,7 +117,7 @@
   (loop [n n]
     (if-let [result (try+ [(thunk)]
                           (catch [:code "Throttling"] e
-                            (warn "Retryable exception while applying configuration" e)
+                            (warn e "Retryable exception while applying configuration")
                             (when (zero? n)
                               (throw+ e))))]
       (result 0)


Add more assertions to core.clj

Add more assertions to core.clj

--- src/play_clj/core.clj
+++ src/play_clj/core.clj
@@ -466,13 +466,11 @@
         (println (:distance screen)) ; the end distance between fingers
         entities))"
   [n & options]
-  ; make sure the options are valid
-  (let [s (format "Unexpected value in (defscreen %s). Make sure you give it
+  (let [s (format "Unexpected value in (defscreen %s). You need to give it
 keywords and functions in pairs."
                   (str n))]
     (assert (even? (count options)) s)
     (assert (= 0 (count (remove keyword? (keys (apply hash-map options))))) s))
-  ; return form calling defscreen*
   `(let [fn-syms# (->> (for [[k# v#] ~(apply hash-map options)]
                          [k# (intern *ns* (symbol (str '~n "-" (name k#))) v#)])
                        flatten
@@ -506,6 +504,8 @@

     (set-screen! my-game main-screen text-screen)"
   [^Game game-object & screen-objects]
+  (assert (isa? (type game-object) Game) "The first argument in set-screen!
+must be the defgame object.")
   (let [run-fn! (fn [k & args]
                   (doseq [screen screen-objects]
                     (apply (get screen k) args)))]
@@ -547,8 +547,13 @@
 `screen` map.

     (update! screen :renderer (stage))"
-  [{:keys [update-fn!] :as screen} & args]
-  (update-fn! assoc args))
+  [screen & args]
+  (assert (some? (:update-fn! screen)) "The first argument in update! must be
+the screen map.")
+  (assert (even? (count args)) "You need to give update! your screen followed by
+pairs of values, such as
+(update! screen :renderer (stage) :camera (orthographic)).")
+  ((:update-fn! screen) assoc args))

 (defn run!
   "Runs a function defined in another screen. You may optionally pass a series
@@ -557,6 +562,10 @@
     (run! my-other-screen :on-show)
     (run! my-other-screen :on-change-color :color :blue)"
   [screen-object fn-name & options]
+  (assert (some? (:screen screen-object)) "The first argument in run! must be
+a defscreen object, such as main-screen.")
+  (assert (keyword? fn-name) "The second argument in run! must be a keyword.")
+  (assert (even? (count options)) "Unexpected argument count in run!.")
   (let [execute-fn! (-> screen-object :screen deref :execute-fn!)
         screen-fn (-> screen-object :options (get fn-name))]
     (apply execute-fn! screen-fn options)


Minor doc updates and tweaks.

Minor doc updates and tweaks.

--- src/puget/printer.clj
+++ src/puget/printer.clj
@@ -12,8 +12,9 @@
 ;; CONTROL VARS

 (def ^:dynamic *strict-mode*
-  "If set, throw an exception if there is no defined canonical print method for
-  a given value."
+  "If true, throw an exception if there is no canonical EDN representation for
+  a given value. This generally applies to any non-primitive value which does
+  not extend puget.data/TaggedValue and is not a built-in collection."
   false)

@@ -23,7 +24,7 @@

 (def ^:dynamic *colored-output*
-  "Output ANSI colored output from print functions."
+  "Output ANSI colored text from print functions."
   false)

@@ -251,8 +252,7 @@
   ([value]
    (cprint value default-opts))
   ([value opts]
-   (binding [*colored-output* true]
-     (pprint value opts))))
+   (with-color (pprint value opts))))

 (defn cprint-str


if language model has a [:generate :lexicon], use that for generation; otherwise use [:lexicon]

--- src/babel/engine.cljc
+++ src/babel/engine.cljc
@@ -56,10 +56,15 @@

         debug (log/debug (str "pre-enrich spec: " spec))

+        ;; if a generate-only lexicon is supplied by the language model, use that.
+        lexicon (if (get-in language-model [:generate :lexicon])
+                  (get-in language-model [:generate :lexicon])
+                  (get-in language-model [:lexicon]))
+
         post-enrich-spec (if (and do-enrich (:enrich language-model))
                            ((:enrich language-model)
                             spec
-                            (:lexicon language-model))
+                            lexicon)
                            spec)

         spec (if (not (empty? post-enrich-spec))
@@ -81,7 +86,7 @@
         ]
     (let [result (generate/generate spec
                                   (:grammar language-model)
-                                  (:lexicon language-model)
+                                  lexicon
                                   (:index language-model)
                                   (:morph language-model))]
       result)))


Tab action display improvements

Tab action display improvements

- Selecting an existing tab when it gets clicked from the list
- Opening a new tab when a URL on our history gets clicked

favicon positioning is ugly, needs to be improved

--- src/booklet/core.cljs
+++ src/booklet/core.cljs
@@ -55,6 +55,12 @@
   (with-meta identity
              {:component-did-mount #(.focus (reagent/dom-node %))}))

+(defn remove-tab
+  "Removed a tab from a collection by id"
+  [col id]
+  (remove #(= (:id %) id) col))
+
+

 ;;;;----------------------------
 ;;;; Handlers
@@ -63,8 +69,6 @@
 (register-handler
   :initialize
   (fn [_ [_ tabs]]
-    (.log js/console tabs)
-    (console/trace "Initializing with:" tabs)
     (go (dispatch [:storage-loaded (<! (storage/get))]))
     {:data {:tabs tabs}}))

@@ -124,7 +128,6 @@
 (register-handler
   :storage-loaded
   (fn [app-state [_ data]]
-    (console/trace "Storage loaded:" data)
     (assoc-in app-state [:data :groups] (:groups data))
     ))

@@ -134,10 +137,6 @@
     (console/trace "Created" (:tab msg))
     (assoc app-state [:data :tabs] (conj (get-in app-state [:data :tabs]) (:tab msg)))))

-(defn remove-tab
-  "Removed a tab from a collection by id"
-  [col id]
-  (remove #(= (:id %) id) col))

 (register-handler
   :log-content
@@ -221,15 +220,27 @@
                   :on-click (:action @modal-info)} (:action-label @modal-info)]
         ]])))

-(defn list-tabs [tabs]
+(defn list-tabs [tabs is-history?]
   (for [tab (sort-by :index tabs)]
-    ^{:key (:id tab)}
-    [:tr
-     [:td (:id tab)]
-     [:td (:title tab)]
-     [:td (:url tab)]]))
-
-(defn tab-list []
+    (let [url     (:url tab)
+          favicon (:favIconUrl tab)
+          action  (if is-history?
+                    {:href url :target "_blank"}
+                    {:on-click #(tabs/update (:id tab) {:highlighted true :active true})}
+                    )]
+      ^{:key (:id tab)}
+      [:tr
+       [:td {:class "col-sm-1"} (if-not is-history? (:id tab))]
+       [:td {:class "col-sm-6"} [:a
+                                 action
+                                 (if favicon
+                                   [:img {:src    favicon
+                                          :width  16
+                                          :height 16}])
+                                 (:title tab)]]
+       [:td {:class "col-sm-5"} url]])))
+
+(defn current-tabs []
   (let [tabs (reaction (filter-tabs @(subscribe [:data :tabs])))]
     (fn []
       [:div
@@ -242,7 +253,7 @@
           [:th "Title"]
           [:th "URL"]]]
         [:tbody
-         (list-tabs @tabs)]
+         (list-tabs @tabs false)]
         ]
        [:button {:on-click #(dispatch [:tabset-save])} "Save me"]
        [:button {:on-click #(go (console/log (<! (storage/get))))} "Get"]
@@ -286,7 +297,7 @@
                [:th "Title"]
                [:th "URL"]]]
              [:tbody
-              (list-tabs (filter-tabs (:tabs group)))]
+              (list-tabs (filter-tabs (:tabs group)) true)]
              ]]))
        ]
       )
@@ -309,7 +320,7 @@

 (defn mount-components []
-  (reagent/render-component [tab-list] (.getElementById js/document "tab-list"))
+  (reagent/render-component [current-tabs] (.getElementById js/document "tab-list"))
   (reagent/render-component [tab-groups] (.getElementById js/document "tab-groups")))


adding get actions by target

adding get actions by target

--- src/celestial/api.clj
+++ src/celestial/api.clj
@@ -119,6 +119,9 @@
         (p/update-action id action)
         (success {:msg "updated actions"}))

+  (GET- "/action/by-target/:type" [^:string type] {:nickname "getActionsByTargetType" :summary "Gets actions that operate on a target type"}
+        (success {:action (p/get-action-index :operates-on type)}))
+
   (GET- "/action/:id" [^:int id] {:nickname "getActions" :summary "Gets actions descriptor"}
         (success {:action (p/get-action id)}))


split pay function into pay and can-pay?

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -23,10 +23,17 @@
 (declare prompt! forfeit trigger-event handle-end-run trash update-advancement-cost update-all-advancement-costs
          update-all-ice update-ice-strength update-breaker-strength all-installed)

-(defn pay [state side card & args]
+(defn can-pay? [state side & args]
   (let [costs (merge-costs (remove #(or (nil? %) (= % [:forfeit])) args))
         forfeit-cost (some #{[:forfeit] :forfeit} args)
         scored (get-in @state [side :scored])]
+    (if (and (every? #(>= (- (get-in @state [side (first %)]) (last %)) 0) costs)
+             (or (not forfeit-cost) (not (empty? scored))))
+      {:costs costs, :forfeit-cost forfeit-cost, :scored scored}
+    )))
+
+(defn pay [state side card & args]
+  (when-let [{:keys [costs forfeit-cost scored]} (apply can-pay? state side args)]
     (when (and (every? #(>= (- (get-in @state [side (first %)]) (last %)) 0) costs)
                (or (not forfeit-cost) (not (empty? scored))))
       (when forfeit-cost


naming

naming

--- src/clj_crud/main.clj
+++ src/clj_crud/main.clj
@@ -22,8 +22,8 @@
                                  (component/stop system))))))

 (defn migrate []
-  (let [db-url (System/getenv "DATABASE_URL")]
-    (assert (.startsWith db-url "postgres:") "DATABASE_URL is required")
+  (let [database-url (System/getenv "DATABASE_URL")]
+    (assert (.startsWith database-url "postgres:") "DATABASE_URL is required")
     (let [db-url (database/db-url-for-heroku database-url)]
       (-> (core/migration-system {:db-connect-string db-url})
           component/start


clustering of discussions at crawl-time is now done

--- src/crawler/crawl.clj
+++ src/crawler/crawl.clj
@@ -789,9 +789,14 @@
                                       extract
                                       stop?
                                       []
-                                      {})))
-
-  ([url-queue visited leaf? extract stop? leaf-paths corpus]
+                                      {}
+                                      (if (leaf? {:anchor-text nil
+                                                  :src-url     nil
+                                                  :body        (:body body)})
+                                        [[entry-point]]
+                                        []))))
+
+  ([url-queue visited leaf? extract stop? leaf-paths corpus leaf-clusters]
      (do
        (Thread/sleep 1000)
        (utils/sayln :queue-size (count url-queue))
@@ -812,7 +817,8 @@
          (cond (or (empty? url-queue)
                    (stop? {:visited    (count visited)
                            :body       body
-                           :corpus     corpus}))
+                           :corpus     corpus
+                           :leaf-clusters leaf-clusters}))
                (do
                  (utils/sayln :crawl-done)
                  {:state  {:url-queue  url-queue
@@ -823,7 +829,9 @@

                   :corpus corpus

-                  :prefix (uri/host (uri/uri url))})
+                  :prefix (uri/host (uri/uri url))
+
+                  :leaf-clusters leaf-clusters})

                :else
                (do (utils/sayln :continuing-crawl)
@@ -849,7 +857,32 @@
                                                {(:url x)
                                                 x}))
                                             {}
-                                            sampled-corpus))]
+                                            sampled-corpus))
+                         new-leaf-clusters (reduce
+                                            (fn [clusters-so-far x]
+                                              (let [to-assign (.indexOf
+                                                               (map
+                                                                (fn [a-cluster]
+                                                                  (some
+                                                                   (fn [c]
+                                                                     (similarity/similar?
+                                                                      (-> c new-corpus :body)
+                                                                      (:body x)))
+                                                                   a-cluster))
+                                                                clusters-so-far)
+                                                               true)]
+                                                (if (neg? to-assign)
+                                                  (into [] (cons [(:url x)] clusters-so-far))
+                                                  (assoc clusters-so-far
+                                                    to-assign
+                                                    (concat
+                                                     [(:url x)]
+                                                     (get clusters-so-far
+                                                          to-assign))))))
+                                            leaf-clusters
+                                            (filter
+                                             :leaf
+                                             sampled-corpus))]
                      (recur new-queue

                             ;; new visited list
@@ -864,4 +897,5 @@
                             extract
                             stop?
                             (concat leaf-paths-obs leaf-paths)
-                            new-corpus))))))))
+                            new-corpus
+                            new-leaf-clusters))))))))


Update dependencies

Update dependencies

--- ring-core/project.clj
+++ ring-core/project.clj
@@ -7,9 +7,9 @@
   :dependencies [[org.clojure/clojure "1.5.1"]
                  [org.clojure/tools.reader "0.9.1"]
                  [ring/ring-codec "1.0.1"]
-                 [commons-io "2.4"]
+                 [commons-io "2.5"]
                  [commons-fileupload "1.3.1"]
-                 [clj-time "0.9.0"]
+                 [clj-time "0.11.0"]
                  [crypto-random "1.2.0"]
                  [crypto-equality "1.0.0"]]
   :profiles


prevent npe if email does not exist

prevent npe if email does not exist

--- src/io/perun/gravatar.clj
+++ src/io/perun/gravatar.clj
@@ -4,7 +4,10 @@
             [gravatar      :as gr]))

 (defn find-gravatar [files source-prop target-prop]
-  (let [add-gravatar #(assoc % target-prop (gr/avatar-url (get % source-prop)))
+  (let [add-gravatar (fn [file]
+                      (if-let [email (get file source-prop)]
+                        (assoc file target-prop (gr/avatar-url email))
+                        file))
         updated-files (map add-gravatar files)]
     (u/info "Added gravatar to %s files\n" (count updated-files))
     updated-files))


Fixed windows markdown frontmatter newline bug

In windows newlines are \r\n, the extra \r causes it to fail
to parse out the frontmatter.

--- src/io/perun/markdown.clj
+++ src/io/perun/markdown.clj
@@ -34,6 +34,8 @@
    :extanchorlinks       Extensions/EXTANCHORLINKS
    :all-optionals        Extensions/ALL_OPTIONALS
    :all-with-optionals   Extensions/ALL_WITH_OPTIONALS})
+
+(def ^:dynamic *yaml-head* #"---\r?\n")

 (defn extensions-map->int [opts]
   (->> opts
@@ -75,7 +77,7 @@
     x))

 (defn parse-file-metadata [file-content]
-  (if-let [metadata-str (substr-between file-content #"---\n" #"---\n")]
+  (if-let [metadata-str (substr-between file-content *yaml-head* *yaml-head*)]
     (if-let [parsed-yaml (normal-colls (yaml/parse-string metadata-str))]
       ; we use `original` file flag to distinguish between generated files
       ; (e.x. created those by plugins)
@@ -84,7 +86,7 @@
     {:original true}))

 (defn remove-metadata [content]
-  (let [splitted (str/split content #"---\n" 3)]
+  (let [splitted (str/split content *yaml-head* 3)]
     (if (> (count splitted) 2)
       (first (drop 2 splitted))
       content)))