Skip to content

Commit

Permalink
Extract side effects
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugh Aristotle Powell committed Jun 4, 2018
1 parent faaeab3 commit 0bf26ba
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 61 deletions.
45 changes: 10 additions & 35 deletions src/lein_tools_deps/deps.clj
@@ -1,38 +1,13 @@
(ns lein-tools-deps.deps
(:require [clojure.java.shell :as shell]
[clojure.java.io :as io]
[clojure.tools.deps.alpha.reader :as reader]
(:require [clojure.java.io :as io]
[lein-tools-deps.file-attributes :as file-attributes]))

(def default-clojure-executables ["/usr/local/bin/clojure"])

(defn- clojure-exe
[config]
(let [clojure-paths (or (:clojure-executables config) default-clojure-executables)
exe (->> clojure-paths
(filter #(.exists (io/file %)))
first)]
(or exe (throw (ex-info "Could not find clojure executable" {:tried-paths clojure-paths})))))

(defn- scrape-clojure-env
[config]
(let [exe (clojure-exe config)
{:keys [out exit] :as result} (shell/sh exe "-Sdescribe")]
(if (zero? exit)
(read-string out)
(throw (ex-info "Unable to locate Clojure's edn files" result)))))

(def clojure-env
"Returns a map describing the environment known to clj/clojure:
{:config-files [ ... ]}"
(memoize scrape-clojure-env))

(defn make-dep-loc-lookup
"Returns a function mapping from a loc(ation)
keyword (either :install, :user or :project) to a file
location. If the value is a string it is returned as is."
[config]
(let [[system-deps home-deps project-deps] (:config-files (clojure-env config))
[{:keys [config-files]}]
(let [[system-deps home-deps project-deps] config-files
project-deps (or project-deps "deps.edn")]
(fn [i]
(if (string? i)
Expand All @@ -44,10 +19,10 @@
(defn canonicalise-dep-locs
"Returns a seq of absolute java.io.File given a seq of dep-refs. Any
relative dep-refs will be made absolute relative to project-root."
[config project-root dep-refs]
(let [location->dep-path (shell/with-sh-dir project-root (make-dep-loc-lookup config))]
[env project-root dep-refs]
(let [location->dep-path (make-dep-loc-lookup env)]
(->> dep-refs
(map #(location->dep-path %))
(map location->dep-path)
(map io/file)
(map (partial file-attributes/absolute-file project-root)))))

Expand Down Expand Up @@ -101,10 +76,10 @@

(defn make-deps
"Reads and merges all of the deps-ref, returning a single deps map"
[{:keys [root] {:keys [config-files] :as config} :lein-tools-deps/config :as project}]
[exists? read-deps env {:keys [root] {:keys [config-files]} :lein-tools-deps/config}]
(as-> config-files $
(canonicalise-dep-locs config (:root project) $)
(filter #(.exists %) $)
(reader/read-deps $)
(canonicalise-dep-locs env root $)
(filter exists? $)
(read-deps $)
(absolute-deps $ root)))

38 changes: 38 additions & 0 deletions src/lein_tools_deps/env.clj
@@ -0,0 +1,38 @@
(ns lein-tools-deps.env
(:require [clojure.java.shell :as shell]
[clojure.java.io :as io])
(:import (java.io File)))

(defmulti exists? class)

(defmethod exists? String [file-path]
(.exists (io/file file-path)))

(defmethod exists? File [file]
(.exists file))

(def default-clojure-executables ["/usr/local/bin/clojure"])

(defn- clojure-exe
[{:keys [clojure-executables]}]
(let [clojure-paths (or clojure-executables default-clojure-executables)
exe (->> clojure-paths
(filter exists?)
first)]
(or exe (throw (ex-info "Could not find clojure executable" {:tried-paths clojure-paths})))))

(defn- scrape-clojure-env
[{:keys [root] config :lein-tools-deps/config}]
(shell/with-sh-dir
root
(let [exe (clojure-exe config)
{:keys [out exit] :as result} (shell/sh exe "-Sdescribe")]
(if (zero? exit)
(read-string out)
(throw (ex-info "Unable to locate Clojure's edn files" result))))))

(def clojure-env
"Returns a map describing the environment known to clj/clojure:
{:config-files [ ... ]}"
(memoize scrape-clojure-env))

1 change: 0 additions & 1 deletion src/lein_tools_deps/lein_project.clj
Expand Up @@ -35,7 +35,6 @@
(into (:paths merged-deps))
(map (partial file-attributes/absolute-path project-root))))


(defn make-classpath
"Resolves additional classpaths, meta merging them into the lein project map"
[{{:keys [classpath-aliases aliases]} :lein-tools-deps/config :as project} deps]
Expand Down
8 changes: 5 additions & 3 deletions src/lein_tools_deps/plugin.clj
@@ -1,6 +1,8 @@
(ns lein-tools-deps.plugin
(:require [leiningen.core.main :as lein]
[clojure.tools.deps.alpha.reader :as reader]
[lein-tools-deps.deps :as deps]
[lein-tools-deps.env :as env]
[lein-tools-deps.lein-project :as lein-project]))

;; load extensions
Expand All @@ -9,8 +11,8 @@
(require 'clojure.tools.deps.alpha.extensions.local)
(require 'clojure.tools.deps.alpha.extensions.maven)

(defn apply-middleware [project]
(let [deps (deps/make-deps project)]
(defn apply-middleware [exists? reader env project]
(let [deps (deps/make-deps exists? reader env project)]
(-> project
(lein-project/resolve-deps deps)
(lein-project/make-classpath deps))))
Expand All @@ -35,7 +37,7 @@
(seq config-files)

(if (every? loc-or-string? config-files)
(apply-middleware project)
(apply-middleware env/exists? reader/read-deps (env/clojure-env project) project)
(do (lein/warn "Every element in :lein-tools-deps/config :config-files must either be a file-path string or one of the location keys" valid-loc-keys)
(lein/exit 1)))

Expand Down
5 changes: 3 additions & 2 deletions test/lein_tools_deps/deps_test.clj
@@ -1,13 +1,14 @@
(ns lein-tools-deps.deps-test
(:require [clojure.test :refer :all]
[clojure.java.io :as io]
[lein-tools-deps.deps :as sut]))
[lein-tools-deps.deps :as sut]
[lein-tools-deps.env :as env]))

(defn absolute-base-path []
(.getAbsolutePath (io/file "")))

(deftest canonicalise-dep-refs-test
(let [canonicalised-files (sut/canonicalise-dep-locs {} (absolute-base-path) [:install "test-cases/basic-deps.edn"])]
(let [canonicalised-files (sut/canonicalise-dep-locs (env/clojure-env {}) (absolute-base-path) [:install "test-cases/basic-deps.edn"])]
(is (every? #(instance? java.io.File %) canonicalised-files))
(is (every? #(.exists %) canonicalised-files))
(is (= 2 (count canonicalised-files))
Expand Down
44 changes: 24 additions & 20 deletions test/lein_tools_deps/plugin_test.clj
@@ -1,7 +1,9 @@
(ns lein-tools-deps.plugin-test
(:require [clojure.test :refer :all]
[clojure.java.io :as io]
[lein-tools-deps.plugin :as sut])
[lein-tools-deps.plugin :as sut]
[clojure.tools.deps.alpha.reader :as reader]
[lein-tools-deps.env :as env])
(:import (clojure.lang ExceptionInfo)))

; The mere presence of this file means that `lein test` will trigger a compilation
Expand All @@ -10,9 +12,11 @@
(defn absolute-base-path []
(.getAbsolutePath (io/file "")))

(def apply-middleware (partial sut/apply-middleware env/exists? reader/read-deps (env/clojure-env {})))

(deftest apply-middleware-to-source-paths
(let [project (sut/apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:config-files ["test-cases/basic-deps.edn"]}})]
(let [project (apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:config-files ["test-cases/basic-deps.edn"]}})]
(is (map? project))
(is (= [(.getAbsolutePath (io/file (absolute-base-path) "src"))
(.getAbsolutePath (io/file (absolute-base-path) "test"))]
Expand All @@ -26,8 +30,8 @@
(is (= ["src" "test"] (:source-paths deps)))))

(deftest apply-middleware-git-to-dependencies
(let [project (sut/apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:config-files ["test-cases/git-deps.edn"]}})]
(let [project (apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:config-files ["test-cases/git-deps.edn"]}})]
(is (map? project))
(let [dependencies (:dependencies project)]
(is (>= (count dependencies) 2))
Expand All @@ -36,37 +40,37 @@
dependencies)))))

(deftest apply-middleware-extra-deps
(let [project (sut/apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:resolve-aliases [:bench]
:config-files ["test-cases/alias-deps.edn"]}})]
(let [project (apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:resolve-aliases [:bench]
:config-files ["test-cases/alias-deps.edn"]}})]
(is (map? project))
(is (= (select-keys project [:dependencies :source-paths])
{:dependencies [['criterium/criterium "0.4.4"]]
:source-paths ()}))))

(deftest apply-middleware-extra-paths
(let [project (sut/apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:classpath-aliases [:extra-paths-test]
:config-files ["test-cases/alias-deps.edn"]}})]
(let [project (apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:classpath-aliases [:extra-paths-test]
:config-files ["test-cases/alias-deps.edn"]}})]
(is (map? project))
(is (= (:source-paths project)
["test"]))))

(deftest apply-middleware-classpath-overrides
(let [project (sut/apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:classpath-aliases [:classpath-overrides-test]
:config-files ["test-cases/alias-deps.edn"]}
:dependencies [['org.clojure/clojure "1.9.0"]]})]
(let [project (apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:classpath-aliases [:classpath-overrides-test]
:config-files ["test-cases/alias-deps.edn"]}
:dependencies [['org.clojure/clojure "1.9.0"]]})]
(is (map? project))
(is (= (:source-paths project)
[(str (absolute-base-path) "/path/to/my/clojure")]))
(is (empty? (:dependencies project)))))

(deftest apply-middleware-all-aliases
(let [project (sut/apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:aliases [:all]
:config-files ["test-cases/alias-deps.edn"]}
:dependencies [['org.clojure/clojure "1.9.0"]]})]
(let [project (apply-middleware {:root (absolute-base-path)
:lein-tools-deps/config {:aliases [:all]
:config-files ["test-cases/alias-deps.edn"]}
:dependencies [['org.clojure/clojure "1.9.0"]]})]
(is (map? project))
(is (= (:source-paths project)
[(str (absolute-base-path) "/path/to/my/clojure")]))
Expand All @@ -80,7 +84,7 @@
(let [project {:lein-tools-deps/config {}}]
(is (= (sut/resolve-dependencies-with-deps-edn project)
project)))

(let [project {:lein-tools-deps/config {:config-files [:bad-location]}}]
(is (thrown? ExceptionInfo (sut/resolve-dependencies-with-deps-edn project))))
(is (thrown? ExceptionInfo (sut/resolve-dependencies-with-deps-edn {}))))
Expand Down

0 comments on commit 0bf26ba

Please sign in to comment.