(#2067) add support for managed-dependencies
This commit provides initial support for `managed-dependencies`, where dependency version numbers may be specified in a separate section called `managed-dependencies`, and those version numbers will be used for any deps in the main `dependencies` section that do not explicitly specify a version number. This is a precursor to being able to specify a "parent" project that could be used to consolidate version numbers of common dependencies across a large number of libraries.
This commit is contained in:
parent
49abe11085
commit
27782edb2e
11 changed files with 111 additions and 45 deletions
|
@ -250,10 +250,12 @@
|
|||
|
||||
(def ^:private get-dependencies-memoized
|
||||
(memoize
|
||||
(fn [dependencies-key {:keys [repositories local-repo offline? update
|
||||
checksum mirrors] :as project}
|
||||
(fn [dependencies-key managed-dependencies-key
|
||||
{:keys [repositories local-repo offline? update
|
||||
checksum mirrors] :as project}
|
||||
{:keys [add-classpath? repository-session-fn] :as args}]
|
||||
{:pre [(every? vector? (get project dependencies-key))]}
|
||||
{:pre [(every? vector? (get project dependencies-key))
|
||||
(every? vector? (get project managed-dependencies-key))]}
|
||||
(try
|
||||
((if add-classpath?
|
||||
pomegranate/add-dependencies
|
||||
|
@ -264,6 +266,7 @@
|
|||
:repositories (->> repositories
|
||||
(map add-repo-auth)
|
||||
(map (partial update-policies update checksum)))
|
||||
:managed-coordinates (get project managed-dependencies-key)
|
||||
:coordinates (get project dependencies-key)
|
||||
:mirrors (->> mirrors
|
||||
(map add-repo-auth)
|
||||
|
@ -407,13 +410,17 @@
|
|||
#(-> % aether/repository-session
|
||||
(pedantic/use-transformer ranges overrides))))
|
||||
|
||||
(defn ^:internal get-dependencies [dependencies-key project & args]
|
||||
(defn ^:internal get-dependencies [dependencies-key managed-dependencies-key
|
||||
project & args]
|
||||
(let [ranges (atom []), overrides (atom [])
|
||||
session (pedantic-session project ranges overrides)
|
||||
args (assoc (apply hash-map args) :repository-session-fn session)
|
||||
trimmed (select-keys project [dependencies-key :repositories :checksum
|
||||
:local-repo :offline? :update :mirrors])
|
||||
deps-result (get-dependencies-memoized dependencies-key trimmed args)]
|
||||
trimmed (select-keys project [dependencies-key managed-dependencies-key
|
||||
:repositories :checksum :local-repo :offline?
|
||||
:update :mirrors])
|
||||
deps-result (get-dependencies-memoized dependencies-key
|
||||
managed-dependencies-key
|
||||
trimmed args)]
|
||||
(pedantic-do (:pedantic? project) @ranges @overrides)
|
||||
deps-result))
|
||||
|
||||
|
@ -486,16 +493,11 @@
|
|||
(doseq [[_ {:keys [native-prefix file]}] snap-deps]
|
||||
(extract-native-dep! native-path file native-prefix))))))
|
||||
|
||||
(defn resolve-dependencies
|
||||
"Delegate dependencies to pomegranate. This will ensure they are
|
||||
downloaded into ~/.m2/repository and that native components of
|
||||
dependencies have been extracted to :native-path. If :add-classpath?
|
||||
is logically true, will add the resolved dependencies to Leiningen's
|
||||
classpath.
|
||||
|
||||
Returns a seq of the dependencies' files."
|
||||
[dependencies-key {:keys [native-path] :as project} & rest]
|
||||
(let [dependencies-tree (apply get-dependencies dependencies-key project rest)
|
||||
(defn resolve-managed-dependencies
|
||||
"TODO"
|
||||
[dependencies-key managed-dependencies-key project & rest]
|
||||
(let [dependencies-tree (apply get-dependencies dependencies-key
|
||||
managed-dependencies-key project rest)
|
||||
jars (->> dependencies-tree
|
||||
(aether/dependency-files)
|
||||
(filter #(re-find #"\.(jar|zip)$" (.getName %))))]
|
||||
|
@ -504,13 +506,33 @@
|
|||
(extract-native-dependencies project jars dependencies-tree))
|
||||
jars))
|
||||
|
||||
(defn resolve-dependencies
|
||||
"Delegate dependencies to pomegranate. This will ensure they are
|
||||
downloaded into ~/.m2/repository and that native components of
|
||||
dependencies have been extracted to :native-path. If :add-classpath?
|
||||
is logically true, will add the resolved dependencies to Leiningen's
|
||||
classpath.
|
||||
|
||||
Returns a seq of the dependencies' files."
|
||||
[dependencies-key project & rest]
|
||||
(apply resolve-managed-dependencies dependencies-key nil project rest))
|
||||
|
||||
(defn managed-dependency-hierarchy
|
||||
"TODO"
|
||||
[dependencies-key managed-dependencies-key project & options]
|
||||
;; TODO: explain private call
|
||||
(if-let [deps-list (#'aether/merge-versions-from-managed-coords
|
||||
(get project dependencies-key)
|
||||
(get project managed-dependencies-key))]
|
||||
(aether/dependency-hierarchy deps-list
|
||||
(apply get-dependencies dependencies-key
|
||||
managed-dependencies-key
|
||||
project options))))
|
||||
|
||||
(defn dependency-hierarchy
|
||||
"Returns a graph of the project's dependencies."
|
||||
[dependencies-key project & options]
|
||||
(if-let [deps-list (get project dependencies-key)]
|
||||
(aether/dependency-hierarchy deps-list
|
||||
(apply get-dependencies dependencies-key
|
||||
project options))))
|
||||
(apply managed-dependency-hierarchy dependencies-key nil project options))
|
||||
|
||||
(defn- normalize-path [root path]
|
||||
(let [f (io/file path) ; http://tinyurl.com/ab5vtqf
|
||||
|
@ -533,7 +555,7 @@
|
|||
(seq
|
||||
(->> (filter ext-dependency? (:dependencies project))
|
||||
(assoc project :dependencies)
|
||||
(resolve-dependencies :dependencies)
|
||||
(resolve-managed-dependencies :dependencies :managed-dependencies)
|
||||
(map (memfn getAbsolutePath)))))
|
||||
|
||||
(defn ^:internal checkout-deps-paths
|
||||
|
@ -561,7 +583,8 @@
|
|||
(:resource-paths project)
|
||||
[(:compile-path project)]
|
||||
(checkout-deps-paths project)
|
||||
(for [dep (resolve-dependencies :dependencies project)]
|
||||
(for [dep (resolve-managed-dependencies
|
||||
:dependencies :managed-dependencies project)]
|
||||
(.getAbsolutePath dep)))
|
||||
:when path]
|
||||
(normalize-path (:root project) path)))
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
((juxt :source-paths :test-paths :resource-paths) project))]
|
||||
(.mkdirs (io/file path))))
|
||||
(write-pom-properties project)
|
||||
(classpath/resolve-dependencies :dependencies project)
|
||||
(classpath/resolve-managed-dependencies :dependencies :managed-dependencies project)
|
||||
(run-prep-tasks project)
|
||||
(deliver @prep-blocker true)
|
||||
(reset! prep-blocker (promise)))
|
||||
|
@ -221,7 +221,7 @@
|
|||
(defn ^:internal classpath-arg [project]
|
||||
(let [classpath-string (string/join java.io.File/pathSeparatorChar
|
||||
(classpath/get-classpath project))
|
||||
agent-tree (classpath/get-dependencies :java-agents project)
|
||||
agent-tree (classpath/get-dependencies :java-agents nil project)
|
||||
;; Seems like you'd expect dependency-files to walk the whole tree
|
||||
;; here, but it doesn't, which is what we want. but maybe a bug?
|
||||
agent-jars (aether/dependency-files (aether/dependency-hierarchy
|
||||
|
@ -334,7 +334,7 @@
|
|||
(when (:debug project)
|
||||
(System/setProperty "clojure.debug" "true"))
|
||||
;; :dependencies are loaded the same way as plugins in eval-in-leiningen
|
||||
(project/load-plugins project :dependencies)
|
||||
(project/load-plugins project :dependencies :managed-dependencies)
|
||||
(doseq [path (classpath/get-classpath project)]
|
||||
(pomegranate/add-classpath path))
|
||||
(doseq [opt (get-jvm-args project)
|
||||
|
|
|
@ -686,13 +686,14 @@
|
|||
(def ^:private registered-wagon-files (atom #{}))
|
||||
|
||||
(defn load-plugins
|
||||
([project key]
|
||||
(when (seq (get project key))
|
||||
([project dependencies-key managed-dependencies-key]
|
||||
(when (seq (get project dependencies-key))
|
||||
(ensure-dynamic-classloader)
|
||||
(let [repos-project (update-in project [:repositories] meta-merge
|
||||
(:plugin-repositories project))]
|
||||
(classpath/resolve-dependencies key repos-project
|
||||
:add-classpath? true)))
|
||||
(classpath/resolve-managed-dependencies
|
||||
dependencies-key managed-dependencies-key repos-project
|
||||
:add-classpath? true)))
|
||||
(doseq [wagon-file (-> (.getContextClassLoader (Thread/currentThread))
|
||||
(.getResources "leiningen/wagons.clj")
|
||||
(enumeration-seq))
|
||||
|
@ -701,6 +702,7 @@
|
|||
(aether/register-wagon-factory! hint (eval factory))
|
||||
(swap! registered-wagon-files conj wagon-file))
|
||||
project)
|
||||
([project dependencies-key] (load-plugins project dependencies-key nil))
|
||||
([project] (load-plugins project :plugins)))
|
||||
|
||||
(defn plugin-vars [project type]
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
(:use [clojure.test]
|
||||
[leiningen.core.classpath])
|
||||
(:require [clojure.java.io :as io]
|
||||
[clojure.set :as set]
|
||||
[leiningen.core.user :as user]
|
||||
[leiningen.test.helper :as lthelper]
|
||||
[leiningen.core.project :as project]))
|
||||
|
@ -17,7 +16,8 @@
|
|||
(defn m2-file [f]
|
||||
(io/file (System/getProperty "user.home") ".m2" "repository" f))
|
||||
|
||||
(def project {:dependencies '[[org.clojure/clojure "1.3.0"]
|
||||
(def project {:managed-dependencies '[[org.clojure/clojure "1.3.0"]]
|
||||
:dependencies '[[org.clojure/clojure]
|
||||
[ring/ring-core "1.0.0"
|
||||
:exclusions [commons-codec]]]
|
||||
:checkout-deps-shares [:source-paths :resource-paths
|
||||
|
@ -38,7 +38,9 @@
|
|||
(m2-file "ring/ring-core/1.0.0/ring-core-1.0.0.jar")
|
||||
(m2-file (str "commons-fileupload/commons-fileupload/1.2.1/"
|
||||
"commons-fileupload-1.2.1.jar"))}
|
||||
(set (resolve-dependencies :dependencies project)))))
|
||||
(set (resolve-managed-dependencies :dependencies
|
||||
:managed-dependencies
|
||||
project)))))
|
||||
|
||||
(deftest test-dependency-hierarchy
|
||||
(doseq [f (reverse (file-seq (io/file (:root project))))]
|
||||
|
@ -49,7 +51,9 @@
|
|||
{[commons-fileupload "1.2.1"] nil
|
||||
[commons-io "1.4"] nil
|
||||
[javax.servlet/servlet-api "2.5"] nil}}
|
||||
(dependency-hierarchy :dependencies project))))
|
||||
(managed-dependency-hierarchy :dependencies
|
||||
:managed-dependencies
|
||||
project))))
|
||||
|
||||
(def directories
|
||||
(vec (map lthelper/pathify
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
[leiningen.core.project :as project])
|
||||
(:import (java.io File)))
|
||||
|
||||
(def project {:dependencies '[[org.clojure/clojure "1.3.0"]]
|
||||
(def project {:managed-dependencies '[[org.clojure/clojure "1.3.0"]]
|
||||
:dependencies '[[org.clojure/clojure]]
|
||||
:root "/tmp/lein-sample-project"
|
||||
:repositories project/default-repositories
|
||||
:target-path "/tmp/lein-sample-project/target"
|
||||
|
|
|
@ -69,8 +69,8 @@
|
|||
(def tree-command
|
||||
"A mapping from the tree-command to the dependency key it should print a tree
|
||||
for."
|
||||
{":tree" :dependencies
|
||||
":plugin-tree" :plugins})
|
||||
{":tree" [:dependencies :managed-dependencies]
|
||||
":plugin-tree" [:plugins nil]})
|
||||
|
||||
|
||||
|
||||
|
@ -121,16 +121,22 @@ force them to be updated, use `lein -U $TASK`."
|
|||
(let [project (project/merge-profiles
|
||||
project
|
||||
[{:pedantic? (quote ^:displace warn)}])
|
||||
hierarchy (classpath/dependency-hierarchy
|
||||
(tree-command command)
|
||||
[dependencies-key managed-dependencies-key] (tree-command command)
|
||||
hierarchy (classpath/managed-dependency-hierarchy
|
||||
dependencies-key
|
||||
managed-dependencies-key
|
||||
project)]
|
||||
(walk-deps hierarchy print-dep))
|
||||
(= command ":verify")
|
||||
(if (user/gpg-available?)
|
||||
(walk-deps (classpath/dependency-hierarchy :dependencies project)
|
||||
(walk-deps (classpath/managed-dependency-hierarchy
|
||||
:dependencies
|
||||
:managed-dependencies
|
||||
project)
|
||||
(partial verify project))
|
||||
(main/abort (str "Could not verify - gpg not available.\n"
|
||||
"See `lein help gpg` for how to setup gpg.")))
|
||||
:else (classpath/resolve-dependencies :dependencies project))
|
||||
:else (classpath/resolve-managed-dependencies
|
||||
:dependencies :managed-dependencies project))
|
||||
(catch DependencyResolutionException e
|
||||
(main/abort (.getMessage e))))))
|
||||
|
|
|
@ -177,7 +177,8 @@ be deactivated."
|
|||
(let [whitelisted (select-keys project project/whitelist-keys)
|
||||
project (-> (project/unmerge-profiles project [:default])
|
||||
(merge whitelisted))
|
||||
deps (->> (classpath/resolve-dependencies :dependencies project)
|
||||
deps (->> (classpath/resolve-managed-dependencies
|
||||
:dependencies :managed-dependencies project)
|
||||
(filter #(.endsWith (.getName %) ".jar")))
|
||||
jars (cons (io/file jar) deps)]
|
||||
(write-components project jars out)))
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
(:use [clojure.test]
|
||||
[leiningen.deps]
|
||||
[leiningen.test.helper :only [sample-project m2-dir native-project
|
||||
managed-deps-project
|
||||
delete-file-recursively]])
|
||||
(:require [clojure.java.io :as io]
|
||||
[leiningen.core.main :as main]
|
||||
[leiningen.core.classpath :as classpath]
|
||||
[leiningen.core.utils :as utils]
|
||||
[leiningen.core.eval :as eval]))
|
||||
|
||||
|
@ -128,3 +127,11 @@
|
|||
(set (for [f (rest (file-seq (io/file (first (eval/native-arch-paths
|
||||
native-project)))))]
|
||||
(.getName f))))))
|
||||
|
||||
(deftest ^:online test-managed-deps
|
||||
(let [managed-deps [["rome" "0.9"] ["jdom" "1.0"]]]
|
||||
(doseq [[n v] managed-deps]
|
||||
(delete-file-recursively (m2-dir n v) :silently))
|
||||
(deps managed-deps-project)
|
||||
(doseq [[n v] managed-deps]
|
||||
(is (.exists (m2-dir n v)) (str n " was not downloaded.")))))
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
|
||||
(def with-classifiers-project (read-test-project "with-classifiers"))
|
||||
|
||||
(def managed-deps-project (read-test-project "managed-deps"))
|
||||
|
||||
(defn abort-msg
|
||||
"Catches main/abort thrown by calling f on its args and returns its error
|
||||
message."
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
[clojure.xml :as xml]
|
||||
[leiningen.test.helper :refer [sample-no-aot-project
|
||||
uberjar-merging-project
|
||||
provided-project]])
|
||||
provided-project
|
||||
managed-deps-project]])
|
||||
(:import (java.io File FileOutputStream)
|
||||
(java.util.zip ZipFile)))
|
||||
|
||||
|
@ -64,3 +65,10 @@
|
|||
_ (uberjar provided-project)]
|
||||
(is (= 1 (:exit (sh "java" "-jar" filename))))
|
||||
(is (= 0 (:exit (sh "java" bootclasspath "-jar" filename))))))
|
||||
|
||||
(deftest test-uberjar-managed-dependencies
|
||||
(uberjar managed-deps-project)
|
||||
(let [filename (str "test_projects/managed-deps/target/"
|
||||
"mgmt-0.99.0-SNAPSHOT-standalone.jar")
|
||||
uberjar-file (File. filename)]
|
||||
(is (= true (.exists uberjar-file)))))
|
12
test_projects/managed-deps/project.clj
Normal file
12
test_projects/managed-deps/project.clj
Normal file
|
@ -0,0 +1,12 @@
|
|||
(def clj-version "1.3.0")
|
||||
|
||||
(defproject mgmt "0.99.0-SNAPSHOT"
|
||||
:description "A test project"
|
||||
|
||||
:managed-dependencies [[~(symbol "org.clojure" "clojure") ~clj-version]
|
||||
[rome ~(str "0." "9")]
|
||||
[ring/ring "1.0.0"]]
|
||||
|
||||
:dependencies [[org.clojure/clojure]
|
||||
[rome/rome nil]
|
||||
[ring]])
|
Loading…
Reference in a new issue