diff --git a/leiningen-core/src/leiningen/core/user.clj b/leiningen-core/src/leiningen/core/user.clj index 58044a23..9d8662a2 100644 --- a/leiningen-core/src/leiningen/core/user.clj +++ b/leiningen-core/src/leiningen/core/user.clj @@ -6,10 +6,15 @@ [leiningen.core.utils :as utils]) (:import (java.util.regex Pattern))) +(defn getenv + "Wrap System/getenv for testing purposes." + [name] + (System/getenv name)) + (defn leiningen-home "Return full path to the user's Leiningen home directory." [] - (let [lein-home (System/getenv "LEIN_HOME") + (let [lein-home (getenv "LEIN_HOME") lein-home (or (and lein-home (io/file lein-home)) (io/file (System/getProperty "user.home") ".lein"))] (.getAbsolutePath (doto lein-home .mkdirs)))) @@ -68,7 +73,7 @@ (defn gpg-program "Lookup the gpg program to use, defaulting to 'gpg'" [] - (or (System/getenv "LEIN_GPG") "gpg")) + (or (getenv "LEIN_GPG") "gpg")) (defn gpg "Shells out to (gpg-program) with the given arguments" @@ -109,23 +114,27 @@ cred)))) (defn- resolve-credential + "Resolve key-value pair from result into a credential, updating result." [source-settings result [k v]] (letfn [(resolve [v] (cond (= :env v) - (System/getenv (str "LEIN_" (str/upper-case (name k)))) + (getenv (str "LEIN_" (str/upper-case (name k)))) (and (keyword? v) (= "env" (namespace v))) - (System/getenv (str/upper-case (name v))) + (getenv (str/upper-case (name v))) (= :gpg v) (get (match-credentials source-settings (credentials)) k) - (coll? v) + (coll? v) ;; collection of places to look (->> (map resolve v) (remove nil?) first) + :else v))] - (assoc result k (resolve v)))) + (if (#{:username :password :passphrase :private-key-file} k) + (assoc result k (resolve v)) + (assoc result k v)))) (defn resolve-credentials "Applies credentials from the environment or ~/.lein/credentials.clj.gpg diff --git a/leiningen-core/test/leiningen/core/test/user.clj b/leiningen-core/test/leiningen/core/test/user.clj new file mode 100644 index 00000000..4d01871a --- /dev/null +++ b/leiningen-core/test/leiningen/core/test/user.clj @@ -0,0 +1,38 @@ +(ns leiningen.core.test.user + (:use clojure.test + leiningen.core.user)) + +(deftest resolving-repo-creds + (with-redefs [credentials-fn (constantly {#"^https://clojars\.org/.*" + {:username "u" :password "p" + :passphrase "looooong" + :private-key-file "./somewhere"}})] + (testing "Literal creds unmolested" + (is (= (resolve-credentials {:url "https://clojars.org/repo" + :username "easily" :password "stolen"}) + {:url "https://clojars.org/repo" + :username "easily" :password "stolen"}))) + (testing "Lookup in enivronment" + (with-redefs [getenv {"LEIN_USERNAME" "flynn" + "CUSTOMENV" "flotilla"}] + (is (= (resolve-credentials {:url "https://clojars.org/repo" + :username :env + :password :env/customenv}) + {:url "https://clojars.org/repo" + :username "flynn" :password "flotilla"})))) + (testing "Check multiple locations" + (with-redefs [getenv {"LEIN_USERNAME" "flynn" + "CUSTOMENV" "flotilla"}] + (is (= (resolve-credentials {:url "https://clojars.org/repo" + :username [:gpg :env] + :password [:env/customenv :gpg]}) + {:url "https://clojars.org/repo" + :username "u" :password "flotilla"})))) + (testing "Custom keys unmolested (and :creds expanded)" + (is (= (resolve-credentials {:url "https://clojars.org/repo" + :creds :gpg + :foo [:gpg "0x00D85767"]}) + {:url "https://clojars.org/repo" + :username "u" :password "p" + :passphrase "looooong" :private-key-file "./somewhere" + :foo [:gpg "0x00D85767"]})))))