Merge pull request #810 from technomancy/last-wins

change with-profile from first-wins to last-wins
This commit is contained in:
Justin Balthrop 2012-10-09 13:10:26 -07:00
commit eda91bdf05
7 changed files with 295 additions and 257 deletions

View file

@ -6,6 +6,7 @@
:dependencies [[org.clojure/clojure "1.4.0"]
[bultitude "0.1.7"]
[classlojure "0.6.6"]
[useful "0.8.6"]
[robert/hooke "1.1.2"]
[com.cemerick/pomegranate "0.0.13"
:exclusions [org.slf4j/slf4j-api]]]

View file

@ -9,12 +9,62 @@
[leiningen.core.utils :as utils]
[leiningen.core.ssl :as ssl]
[leiningen.core.user :as user]
[leiningen.core.classpath :as classpath])
[leiningen.core.classpath :as classpath]
[useful.fn :refer [fix]]
[useful.seq :refer [update-first]]
[useful.map :refer [update update-each]])
(:import (clojure.lang DynamicClassLoader)
(java.io PushbackReader)))
;; # Project definition and normalization
(defn artifact-map
[id]
{:artifact-id (name id)
:group-id (or (namespace id) (name id))})
(defn exclusion-map
"Transform an exclusion vector into a map that is easier to combine with
meta-merge. This allows a profile to override specific exclusion options."
[spec]
(when-let [[id & {:as opts}] (fix spec symbol? vector)]
(-> opts
(merge (artifact-map id))
(with-meta (meta spec)))))
(defn exclusion-vec
"Transform an exclusion map back into a vector of the form:
[name/group & opts]"
[exclusion]
(when-let [{:keys [artifact-id group-id]} exclusion]
(into [(symbol group-id artifact-id)]
(apply concat (dissoc exclusion :artifact-id :group-id)))))
(defn dependency-map
"Transform a dependency vector into a map that is easier to combine with
meta-merge. This allows a profile to override specific dependency options."
[dep]
(when-let [[id version & {:as opts}] dep]
(-> opts
(merge (artifact-map id))
(assoc :version version)
(update :exclusions #(when % (map exclusion-map %)))
(with-meta (meta dep)))))
(defn dependency-vec
"Transform a dependency map back into a vector of the form:
[name/group \"version\" & opts]"
[dep]
(when-let [{:keys [artifact-id group-id version]} dep]
(-> dep
(update :exclusions #(when % (map exclusion-vec %)))
(dissoc :artifact-id :group-id :version)
(->> (apply concat)
(into [(symbol group-id artifact-id) version]))
(with-meta (meta dep)))))
(declare meta-merge)
(defn- unquote-project
"Inside defproject forms, unquoting (~) allows for arbitrary evaluation."
[args]
@ -26,23 +76,61 @@
identity
args))
(def defaults {:source-paths ["src"]
:resource-paths ["resources"]
:test-paths ["test"]
:native-path "target/native"
:compile-path "target/classes"
:target-path "target"
:prep-tasks ["javac" "compile"]
:repositories [["central" {:url "http://repo1.maven.org/maven2/"}]
;; TODO: point to releases-only before 2.0 is out
["clojars" {:url "https://clojars.org/repo/"}]]
:deploy-repositories [["clojars" {:url "https://clojars.org/repo/"
:username :gpg
:password :gpg}]]
:jar-exclusions [#"^\."]
:jvm-opts ["-XX:+TieredCompilation"]
:certificates ["clojars.pem"]
:uberjar-exclusions [#"(?i)^META-INF/[^/]*\.(SF|RSA|DSA)$"]})
(def defaults
{:source-paths ["src"]
:resource-paths ["resources"]
:test-paths ["test"]
:native-path "target/native"
:compile-path "target/classes"
:target-path "target"
:prep-tasks ["javac" "compile"]
:jar-exclusions [#"^\."]
:jvm-opts ["-XX:+TieredCompilation"]
:certificates ["clojars.pem"]
:uberjar-exclusions [#"(?i)^META-INF/[^/]*\.(SF|RSA|DSA)$"]})
(defn- dep-key
"The unique key used to dedupe dependencies."
[[id version & opts]]
(-> (apply hash-map opts)
(select-keys [:classifier :extension])
(assoc :id id)))
(defn- add-dep [deps dep]
(let [k (dep-key dep)]
(update-first deps #(= k (dep-key %))
(fn [existing]
(dependency-vec
(meta-merge (dependency-map existing)
(dependency-map dep)))))))
(defn- add-repo [repos repo]
(let [[id opts] repo
opts (fix opts string? (partial hash-map :url))]
(update-first repos #(= id (first %))
(fn [[_ existing]]
[id (meta-merge existing opts)]))))
(def empty-dependencies
(with-meta [] {:reduce add-dep}))
(def empty-repositories
(with-meta [] {:reduce add-repo}))
(def empty-paths
(with-meta [] {:prepend true}))
(def default-repositories
(with-meta
[["central" {:url "http://repo1.maven.org/maven2/"}]
;; TODO: point to releases-only before 2.0 is out
["clojars" {:url "https://clojars.org/repo/"}]]
{:reduce add-repo}))
(def deploy-repositories
(with-meta
[["clojars" {:url "https://clojars.org/repo/", :password :gpg, :username :gpg}]]
{:reduce add-repo}))
(defn make
([project project-name version root]
@ -53,12 +141,27 @@
:version version
:root root)))
([project]
(-> (merge defaults project)
(dissoc :eval-in-leiningen :omit-default-repositories)
(assoc :eval-in (or (:eval-in project)
(if (:eval-in-leiningen project)
:leiningen, :subprocess))
:offline? (not (nil? (System/getenv "LEIN_OFFLINE")))))))
(let [repos (if (:omit-default-repositories project)
(do (println "WARNING:"
":omit-default-repositories is deprecated;"
"use :repositories ^:replace [...] instead.")
empty-repositories)
default-repositories)]
(meta-merge
{:repositories repos
:plugin-repositories repos
:deploy-repositories deploy-repositories
:plugins empty-dependencies
:dependencies empty-dependencies
:source-paths empty-paths
:resource-paths empty-paths
:test-paths empty-paths}
(-> (merge defaults project)
(dissoc :eval-in-leiningen :omit-default-repositories)
(assoc :eval-in (or (:eval-in project)
(if (:eval-in-leiningen project)
:leiningen, :subprocess))
:offline? (not (nil? (System/getenv "LEIN_OFFLINE")))))))))
(defmacro defproject
"The project.clj file must either def a project map or call this macro.
@ -69,73 +172,20 @@
(def ~'project
(make args# '~project-name ~version root#))))
(defn- de-dupe-repo [[repositories seen?] [id settings]]
;; repositories from user profiles can be just credentials, so check :url
(if (or (seen? id) (not (:url settings)))
[repositories seen?]
[(conj repositories [id settings]) (conj seen? id)]))
(defn- add-exclusions [exclusions dep]
(dependency-vec
(meta-merge (dependency-map dep)
{:exclusions (map exclusion-map exclusions)})))
(defn- mapize-settings [repositories]
(for [[id settings] repositories]
[id (if (string? settings) {:url settings} settings)]))
(defn normalize-repos [project]
;; TODO: got to be a way to tidy this up
(let [project (update-in project [:repositories] mapize-settings)
project (if (:deploy-repositories project)
(update-in project [:deploy-repositories] mapize-settings)
project)
project (if (:plugin-repositories project)
(update-in project [:plugin-repositories] mapize-settings)
project)]
(assoc project :repositories
(first (reduce de-dupe-repo
(if-not (:omit-default-repositories project)
[(:repositories defaults)
(set (map first (:repositories defaults)))]
[[] #{}]) (:repositories project))))))
(defn- without-version [[id version & other]]
(-> (apply hash-map other)
(select-keys [:classifier :extension])
(assoc :id id)))
(defn- dedupe-step [[deps seen] x]
(if (seen (without-version x))
;; this would be so much cleaner if we could just re-use profile-merge
;; logic, but since :dependencies are a vector, the :replace/:displace
;; calculations don't apply to nested vectors inside :dependencies.
(let [[seen-dep] (filter #(= (first %) (first x)) deps)]
(if (or (:displace (meta seen-dep)) (:replace (meta x)))
[(assoc deps (.indexOf deps seen-dep) x) seen]
[deps seen]))
[(conj deps x) (conj seen (without-version x))]))
(defn- dedupe-deps [deps]
(first (reduce dedupe-step [[] #{}] deps)))
(defn- exclude [exclusions deps dep]
(conj deps
(if (empty? exclusions)
dep
(let [exclusions-offset (.indexOf dep :exclusions)]
(if (pos? exclusions-offset)
(update-in dep [(inc exclusions-offset)]
(comp vec distinct (partial into exclusions)))
(-> dep
(conj :exclusions)
(conj exclusions)))))))
(defn- add-exclusions [deps exclusions]
(reduce (partial exclude exclusions) [] deps))
(defn normalize-deps [project]
(-> project
(update-in [:dependencies] dedupe-deps)
(update-in [:dependencies] add-exclusions (:exclusions project))))
(defn normalize-plugins [project]
(update-in project [:plugins] dedupe-deps))
(defn- add-global-exclusions [project]
(let [{:keys [dependencies exclusions]} project]
(if-let [exclusions (and (seq dependencies) (seq exclusions))]
(assoc project
:dependencies (with-meta
(mapv (partial add-exclusions exclusions)
dependencies)
(meta dependencies)))
project)))
(defn- absolutize [root path]
(str (if (.isAbsolute (io/file path))
@ -152,17 +202,7 @@
:else project))
(defn absolutize-paths [project]
(let [project (reduce absolutize-path project (keys project))]
(assoc project :compile-path (or (:compile-path project)
(str (io/file (:target-path project)
"classes"))))))
(defn remove-aliases [project]
(dissoc project :deps :eval-in-leiningen))
(def ^{:arglists '([project])} normalize
"Normalize project map to standard representation."
(comp normalize-repos normalize-deps absolutize-paths remove-aliases))
(reduce absolutize-path project (keys project)))
;; # Profiles: basic merge logic
@ -175,7 +215,7 @@
(def default-profiles
"Profiles get merged into the project map. The :dev, :provided, and :user
profiles are active by default."
(atom {:default [:dev :provided :user :base]
(atom {:default [:base :user :provided :dev]
:base {:resource-paths ["dev-resources"]
:plugins [['lein-newnew "0.3.5"]]
:checkout-deps-shares [:source-paths
@ -188,34 +228,48 @@
(defn- meta-merge
"Recursively merge values based on the information in their metadata."
[result latter]
(cond (-> result meta :displace)
latter
[left right]
(cond (or (-> left meta :displace)
(-> right meta :replace))
(with-meta right
(merge (-> left meta (dissoc :displace))
(-> right meta (dissoc :replace))))
(-> latter meta :replace)
latter
(-> left meta :reduce)
(-> left meta :reduce
(reduce left right)
(with-meta (meta left)))
;; TODO: last-wins breaks here
(and (map? result) (map? latter))
(merge-with meta-merge result latter)
(nil? left) right
(nil? right) left
(and (set? result) (set? latter))
(set/union latter result)
(and (map? left) (map? right))
(merge-with meta-merge left right)
(and (coll? result) (coll? latter))
(concat latter result)
(and (set? left) (set? right))
(set/union right left)
(= (class result) (class latter)) latter
(and (coll? left) (coll? right))
(if (or (-> left meta :prepend)
(-> right meta :prepend))
(-> (concat right left)
(with-meta (merge (meta left)
(select-keys (meta right) [:displace]))))
(concat left right))
:else (doto latter (println "has a type mismatch merging profiles."))))
(= (class left) (class right)) right
:else
(do (println left "and" right "have a type mismatch merging profiles.")
right)))
(defn- apply-profiles [project profiles]
;; We reverse because we want profile values to override the project, so we
;; need "last wins" in the reduce, but we want the first profile specified by
;; the user to take precedence.
(reduce (partial merge-with meta-merge)
(reduce (fn [project profile]
(with-meta
(meta-merge project profile)
(meta-merge (meta project) (meta profile))))
project
(reverse profiles)))
profiles))
(defn- lookup-profile
"Lookup a profile in the given profiles map, warning when the profile doesn't
@ -266,18 +320,11 @@
(when-not (pomegranate/modifiable-classloader? cl)
(.setContextClassLoader thread (DynamicClassLoader. cl)))))
(defn- merge-plugin-repositories [project]
(if-let [pr (:plugin-repositories project)]
(if (:omit-default-repositories project)
(assoc project :repositories pr)
(update-in project [:repositories] concat pr))
project))
(defn load-plugins
([project key]
(when (seq (get project key))
(ensure-dynamic-classloader)
(classpath/resolve-dependencies key (merge-plugin-repositories project)
(classpath/resolve-dependencies key project
:add-classpath? true))
(doseq [wagon-file (-> (.getContextClassLoader (Thread/currentThread))
(.getResources "leiningen/wagons.clj")
@ -290,9 +337,8 @@
(defn plugin-vars [project type]
(for [[plugin _ & {:as opts}] (:plugins project)
:when (get opts type true)]
(with-meta (symbol (str (name plugin) ".plugin")
(name type))
{:optional true})))
(-> (symbol (str (name plugin) ".plugin") (name type))
(with-meta {:optional true}))))
(defn- plugin-hooks [project]
(plugin-vars project :hooks))
@ -354,13 +400,14 @@
"Compute a fresh version of the project map, including and excluding the
specified profiles."
[project include-profiles & [exclude-profiles]]
(let [without-profiles (:without-profiles (meta project) project)
(let [project (:without-profiles (meta project) project)
profile-map (apply dissoc (read-profiles project) exclude-profiles)
profiles (map (partial lookup-profile profile-map) include-profiles)]
(-> without-profiles
(-> project
(apply-profiles profiles)
(normalize)
(vary-meta merge {:without-profiles without-profiles
(absolutize-paths)
(add-global-exclusions)
(vary-meta merge {:without-profiles project
:included-profiles include-profiles
:excluded-profiles exclude-profiles}))))

View file

@ -28,11 +28,11 @@
:eval-in :leiningen,
:license {:name "Eclipse Public License"}
:dependencies '[[leiningen-core "2.0.0-SNAPSHOT"]
[clucy "0.2.2" :exclusions [org.clojure/clojure]]
[lancet "1.0.1"]
:dependencies '[[leiningen-core/leiningen-core "2.0.0-SNAPSHOT"]
[clucy/clucy "0.2.2" :exclusions [[org.clojure/clojure]]]
[lancet/lancet "1.0.1"]
[robert/hooke "1.1.2"]
[stencil "0.2.0"]],
[stencil/stencil "0.2.0"]],
:twelve 12 ; testing unquote
:repositories [["central" {:url "http://repo1.maven.org/maven2/"}]
@ -41,73 +41,82 @@
(deftest test-read-project
(let [actual (read (.getFile (io/resource "p1.clj")))]
(doseq [[k v] expected]
(is (= (k actual) v)))
(is (= v (k actual))))
(doseq [[k path] paths
:when (string? path)]
(is (= (k actual) (str (:root actual) "/" path))))
(is (= (str (:root actual) "/" path)
(k actual))))
(doseq [[k path] paths
:when (coll? path)]
(is (= (k actual) (for [p path] (str (:root actual) "/" p)))))))
(is (= (for [p path] (str (:root actual) "/" p))
(k actual))))))
;; TODO: test omit-default
;; TODO: test reading project that doesn't def project
(def test-profiles (atom {:qa {:resource-paths ["/etc/myapp"]}
:test {:resource-paths ["test/hi"]}
:repl {:dependencies '[[org.clojure/tools.nrepl
"0.2.0-beta6"
:exclusions
[org.clojure/clojure]]
[org.thnetos/cd-client "0.3.4"
:exclusions
[org.clojure/clojure]]]}
:repl {:dependencies
'[[org.clojure/tools.nrepl "0.2.0-beta6"
:exclusions [org.clojure/clojure]]
[org.thnetos/cd-client "0.3.4"
:exclusions [org.clojure/clojure]]]}
:tes :test
:dev {:test-paths ["test"]}}))
(deftest test-merge-profile-paths
(with-redefs [default-profiles test-profiles]
(is (= ["/etc/myapp" "test/hi" "blue-resources" "resources"]
(-> {:resource-paths ["resources"]
:profiles {:blue {:resource-paths ["blue-resources"]}}}
(merge-profiles [:qa :tes :blue])
(-> (make
{:resource-paths ["resources"]
:profiles {:blue {:resource-paths ["blue-resources"]}}})
(merge-profiles [:blue :tes :qa])
:resource-paths)))
(is (= ["/etc/myapp" "test/hi" "blue-resources"]
(-> {:resource-paths ^:displace ["resources"]
:profiles {:blue {:resource-paths ["blue-resources"]}}}
(merge-profiles [:qa :tes :blue])
(-> (make
{:resource-paths ^:displace ["resources"]
:profiles {:blue {:resource-paths ["blue-resources"]}}})
(merge-profiles [:blue :tes :qa])
:resource-paths)))
(is (= ["replaced"]
(-> {:resource-paths ["resources"]
:profiles {:blue {:resource-paths ^:replace ["replaced"]}}}
(merge-profiles [:blue :qa :tes])
(-> (make
{:resource-paths ["resources"]
:profiles {:blue {:resource-paths ^:replace ["replaced"]}}})
(merge-profiles [:tes :qa :blue])
:resource-paths)))
(is (= {:url "http://" :username "u" :password "p"}
(-> {:repositories [["foo" {:url "http://" :creds :gpg}]]
:profiles {:blue {:repositories {"foo"
^:replace {:url "http://"
:username "u"
:password "p"}}}}}
(-> (make
{:repositories [["foo" {:url "http://" :creds :gpg}]]
:profiles {:blue {:repositories {"foo"
^:replace {:url "http://"
:username "u"
:password "p"}}}}})
(merge-profiles [:blue :qa :tes])
:repositories
last last)))))
;; TODO
(deftest test-merge-profile-deps
(with-redefs [default-profiles test-profiles]
(let [project {:resource-paths ["resources"]
:profiles {:dev {:dependencies
'[^:displace [org.thnetos/cd-client "0.3.0"]
[org.clojure/tools.nrepl "0.2.0-beta2"]]}}}
cp (-> (merge-profiles project [:dev :repl])
(classpath/get-classpath))]
(is (some (partial re-find #"nrepl-0.2.0-beta2") cp))
(is (some (partial re-find #"cd-client-0.3.4") cp)))))
(let [project (make
{:resource-paths ["resources"]
:dependencies '[^:displace [org.foo/bar "0.1.0" :foo [1 2]]
[org.foo/baz "0.2.0" :foo [1 2]]
[org.foo/zap "0.3.0" :foo [1 2]]]
:profiles {:dev {:dependencies
'[[org.foo/bar "0.1.2"]
[org.foo/baz "0.2.1"]
^:replace [org.foo/zap "0.3.1"]]}}})]
(is (= '[[org.foo/bar "0.1.2"]
[org.foo/baz "0.2.1" :foo [1 2]]
[org.foo/zap "0.3.1"]]
(-> (merge-profiles project [:dev])
:dependencies))))))
(deftest test-global-exclusions
(is (= '[[org.clojure/clojure]
[org.clojure/clojure pomegranate]
[org.clojure/clojure]]
(map #(:exclusions (apply hash-map %))
(is (= '[[[org.clojure/clojure]]
[[pomegranate/pomegranate] [org.clojure/clojure]]
[[org.clojure/clojure]]]
(map #(distinct (:exclusions (apply hash-map %)))
(-> {:dependencies
'[[lancet "1.0.1"]
[leiningen-core "2.0.0-SNAPSHOT" :exclusions [pomegranate]]
@ -158,66 +167,51 @@
:without-profiles)))))
(deftest test-merge-anon-profiles
(let [expected-result {:A 1 :C 3 :profiles {:a {:A 1}
:b {:B 2}}
:repositories [["central" {:url "http://repo1.maven.org/maven2/"}]
["clojars" {:url "https://clojars.org/repo/"}]]
:dependencies [], :compile-path "classes"}]
(is (= expected-result
(-> {:profiles {:a {:A 1} :b {:B 2}}}
(merge-profiles [:a {:C 3}]))))))
(is (= {:A 1, :C 3}
(-> {:profiles {:a {:A 1} :b {:B 2}}}
(merge-profiles [{:C 3} :a])
(dissoc :profiles)))))
(deftest test-composite-profiles
(let [expected-result {:A '(2 3 1), :B 2, :C 3,
:repositories [["central" {:url "http://repo1.maven.org/maven2/"}]
["clojars" {:url "https://clojars.org/repo/"}]]
:dependencies [], :compile-path "classes"}]
(is (= expected-result
(-> {:profiles {:a [:c :b]
:b [:d {:A [1] :B 1 :C 1}]
:c {:A [2] :B 2}
:d {:A [3] :C 3}}}
(merge-profiles [:a])
(dissoc :profiles))))))
(is (= {:A '(1 3 2), :B 2, :C 3}
(-> {:profiles {:a [:b :c]
:b [{:A [1] :B 1 :C 1} :d]
:c {:A [2] :B 2}
:d {:A [3] :C 3}}}
(merge-profiles [:a])
(dissoc :profiles)))))
(deftest test-override-default
(let [expected-result {:A 1, :B 2, :C 3
:repositories [["central" {:url "http://repo1.maven.org/maven2/"}]
["clojars" {:url "https://clojars.org/repo/"}]]
:dependencies [], :compile-path "classes"}]
(is (= expected-result
(-> {:profiles {:a {:A 1 :B 2}
:b {:B 2 :C 2}
:c {:C 3}
:default [:c :b :a]}}
(merge-profiles [:default])
(dissoc :profiles))))))
(is (= {:A 1, :B 2, :C 3}
(-> {:profiles {:a {:A 1 :B 2}
:b {:B 2 :C 2}
:c {:C 3}
:default [:a :b :c]}}
(merge-profiles [:default])
(dissoc :profiles)))))
(deftest test-unmerge-profiles
(let [expected-result {:A 1 :C 3 :profiles {:a {:A 1}
:b {:B 2}
:c {:C 3}}
:repositories [["central" {:url "http://repo1.maven.org/maven2/"}]
["clojars" {:url "https://clojars.org/repo/"}]]
:dependencies [], :compile-path "classes"}]
(is (= expected-result
(let [expected {:A 1 :C 3}]
(is (= expected
(-> {:profiles {:a {:A 1}
:b {:B 2}
:c {:C 3}}}
(merge-profiles [:a :b :c])
(unmerge-profiles [:b]))))
(is (= expected-result
(unmerge-profiles [:b])
(dissoc :profiles))))
(is (= expected
(-> {:profiles {:a {:A 1}
:b {:B 2}
:c {:C 3}}}
(merge-profiles [:a :b :c {:D 4}])
(unmerge-profiles [:b {:D 4}]))))))
(unmerge-profiles [:b {:D 4}])
(dissoc :profiles))))))
(deftest test-dedupe-deps
(is (= '[[org.clojure/clojure "1.4.0"]
(is (= '[[org.clojure/clojure "1.3.0"]
[org.clojure/clojure "1.3.0" :classifier "sources"]]
(-> {:dependencies '[[org.clojure/clojure "1.4.0"]
[org.clojure/clojure "1.3.0" :classifier "sources"]
[org.clojure/clojure "1.3.0"]]}
(normalize-deps)
(-> (make
{:dependencies '[[org.clojure/clojure "1.4.0"]
[org.clojure/clojure "1.3.0" :classifier "sources"]
[org.clojure/clojure "1.3.0"]]})
(:dependencies)))))

View file

@ -177,6 +177,13 @@
[key (name val)]))]
[:licenses [:license tags]]))))
(defn- resource-tags [project type]
(if-let [resources (seq (:resource-paths project))]
(let [types (keyword (str (name type) "s"))]
(vec (concat [types]
(for [resource resources]
[type [:directory resource]]))))))
(defmethod xml-tags ::build
([_ [project test-project]]
(let [[src & extra-src] (concat (:source-paths project)
@ -185,14 +192,8 @@
[:build
[:sourceDirectory src]
(xml-tags :testSourceDirectory test)
(if-let [resources (seq (:resource-paths project))]
(vec (concat [:resources]
(for [resource resources]
[:resource [:directory resource]]))))
(if-let [resources (seq (:resource-paths test-project))]
(vec (concat [:testResources]
(for [resource resources]
[:testResource [:directory resource]]))))
(resource-tags project :resource)
(resource-tags test-project :testResource)
(if-let [extensions (seq (:extensions project))]
(vec (concat [:extensions]
(for [[dep version] extensions]

View file

@ -141,7 +141,7 @@ Also accepts a second parameter for fetching successive pages."
;; Maven's indexer requires over 1GB of free space for a <100M index
(let [orig-tmp (System/getProperty "java.io.tmpdir")
new-tmp (io/file (user/leiningen-home) "indices" "tmp")
project (or project (project/normalize-repos project/defaults))
project (or project (project/make {}))
contexts (doall (map add-context (:repositories project)))]
(try
(.mkdirs new-tmp)

View file

@ -25,8 +25,7 @@
rests (mapcat rest forms)
;; This won't pick up :jvm-args that come from profiles, but it
;; at least gets us :dependencies.
project (project/normalize-deps (assoc project :dependencies
(apply concat deps)))
project (project/merge-profiles project {:dependencies deps})
command (eval/shell-command project (concat '(do) inits rests))]
(string/join " " (if (win-batch?)
(map quote-arg command)

View file

@ -33,14 +33,10 @@
([project profile]
(with-profile project :test-pom profile))
([project name profile]
(let [{:keys [included-profiles
without-profiles]} (meta project)]
(-> without-profiles
(update-in [:profiles] #(assoc % name profile))
(project/merge-profiles
(if (some #{name} included-profiles)
included-profiles
(conj included-profiles name)))))))
(-> project
(vary-meta update-in [:without-profiles :profiles]
assoc name profile)
(project/merge-profiles [name]))))
(deftest test-pom-default-values
(let [xml (xml/parse-str (make-pom sample-project))]
@ -179,37 +175,37 @@
[[ring-mock
:classifier "cla"
:extension "dom"]]]]})))]
(is (= ["peridot" "org.clojure" "rome" "ring"]
(is (= ["org.clojure" "rome" "ring" "peridot"]
(map #(first-in % [:dependency :groupId])
(deep-content xml [:project :dependencies]))))
(is (= [ "peridot" "clojure" "rome" "ring"]
(is (= ["clojure" "rome" "ring" "peridot"]
(map #(first-in % [:dependency :artifactId])
(deep-content xml [:project :dependencies]))))
(is (= ["0.0.5" "1.3.0" "0.9" "1.0.0"]
(is (= ["1.3.0" "0.9" "1.0.0" "0.0.5"]
(map #(first-in % [:dependency :version])
(deep-content xml [:project :dependencies]))))
(is (= ["provided" nil nil nil]
(is (= [nil nil nil "provided"]
(map #(first-in % [:dependency :scope])
(deep-content xml [:project :dependencies]))))
(is (= ["true" nil nil nil]
(is (= [nil nil nil "true"]
(map #(first-in % [:dependency :optional])
(deep-content xml [:project :dependencies]))))
(is (= ["sources" nil nil nil]
(is (= [nil nil nil "sources"]
(map #(first-in % [:dependency :classifier])
(deep-content xml [:project :dependencies]))))
(is (= ["pom" nil nil nil]
(is (= [nil nil nil "pom"]
(map #(first-in % [:dependency :type])
(deep-content xml [:project :dependencies]))))
(is (= ["ring-mock" nil nil nil]
(is (= [nil nil nil "ring-mock"]
(map #(first-in % [:dependency :exclusions :exclusion :artifactId])
(deep-content xml [:project :dependencies]))))
(is (= ["ring-mock" nil nil nil]
(is (= [nil nil nil "ring-mock"]
(map #(first-in % [:dependency :exclusions :exclusion :groupId])
(deep-content xml [:project :dependencies]))))
(is (= ["cla" nil nil nil]
(is (= [nil nil nil "cla"]
(map #(first-in % [:dependency :exclusions :exclusion :classifier])
(deep-content xml [:project :dependencies]))))
(is (= ["dom" nil nil nil]
(is (= [nil nil nil "dom"]
(map #(first-in % [:dependency :exclusions :exclusion :type])
(deep-content xml [:project :dependencies])))))
(let [xml (xml/parse-str
@ -219,19 +215,19 @@
:scope "provided"
:exclusions
[ring-mock]]]})))]
(is (= ["peridot" "org.clojure" "rome" "ring"]
(is (= ["org.clojure" "rome" "ring" "peridot"]
(map #(first-in % [:dependency :groupId])
(deep-content xml [:project :dependencies]))))
(is (= [ "peridot" "clojure" "rome" "ring"]
(is (= ["clojure" "rome" "ring" "peridot"]
(map #(first-in % [:dependency :artifactId])
(deep-content xml [:project :dependencies]))))
(is (= ["0.0.5" "1.3.0" "0.9" "1.0.0"]
(is (= ["1.3.0" "0.9" "1.0.0" "0.0.5"]
(map #(first-in % [:dependency :version])
(deep-content xml [:project :dependencies]))))
(is (= ["provided" nil nil nil]
(is (= [nil nil nil "provided"]
(map #(first-in % [:dependency :scope])
(deep-content xml [:project :dependencies]))))
(is (= ["ring-mock" nil nil nil]
(is (= [nil nil nil "ring-mock"]
(map #(first-in % [:dependency :exclusions :exclusion :artifactId])
(deep-content xml [:project :dependencies]))))
(is (= [nil nil nil nil]