lib.aether interface for org.eclipse.aether

Author: Chris Zheng  (z@caudate.me)
Date: 27 November 2018
Repository: https://github.com/zcaudate/hara
Version: 3.0.2

1    Introduction

hara.lib.aether is used to as an interface to manage dependencies. It is meant as an alternative to pomegranate for package installation, dependency resolution and other tasks.

1.1    Installation

Add to project.clj dependencies:

[hara/lib.aether "3.0.2"]

All functions are in the hara.lib.aether namespace.

 (use (quote hara.lib.aether))

2    API



aether ^

creates an `Aether` object

v 3.0
(defn aether
  ([] (aether {}))
  ([config]
   (let [system  (system/repository-system)
         session (->> (select-keys config [:local-repo])
                      (session/session system))]
     (-> +defaults+
         (merge {:system system
                 :session session})
         (map->Aether)))))
link
(aether) => (contains-in {:repositories (contains [{:id "clojars", :type "default", :url "https://clojars.org/repo"} {:id "central", :type "default", :url "https://repo1.maven.org/maven2/"}] :in-any-order :gaps-ok), :system org.eclipse.aether.RepositorySystem :session org.eclipse.aether.RepositorySystemSession})

artifact->dependency ^

converts an artifact to a dependency

v 3.0
(defn artifact->dependency
  [artifact]
  (let [coord (cond (artifact/coord? artifact)
                    artifact
                    
                    (map? artifact)
                    (apply vector (:name artifact) (:version artifact)
                           (mapcat identity (dissoc artifact :name :version)))

                    :else
                    (artifact/artifact :coord artifact))
        [name version & {:keys [scope exclusions]}] coord]
    (object/from-data {:artifact [name version]
                       :scope scope
                       :exclusions exclusions}
                      Dependency)))
link
(artifact->dependency '[org.clojure/clojure "1.8.0" :scope "compile" :exclusions [org.asm/compile]]) ;; #dep{:artifact "org.clojure:clojure:jar:1.8.0", ;; :exclusions ["org.asm:compile:jar:"], ;; :optional false, :scope "compile", :optional? false} => org.eclipse.aether.graph.Dependency

collect-dependencies ^

getting the dependencies of a repo using pom files

v 3.0
(defn collect-dependencies
  ([coords]
   (collect-dependencies coords {}))
  ([coords opts]
   (collect-dependencies (base/aether) coords opts))
  ([{:keys [system session repositories]} coords opts]
   (binding [listener/*progress* (atom [])
             listener/*pairs* (atom {})]
     (let [opts   (nested/merge-nested {:type :defalut
                                        :return :hierarchy
                                        :print {:hierarchy true
                                                :title true
                                                :timing true}}
                                       opts)
           reqm   (cond (and (sequential? coords)
                             (not (artifact/coord? coords)))
                        {:dependencies (mapv artifact->dependency coords)}

                        :else
                        {:root (artifact->dependency coords)})
           request (request/collect-request
                    (assoc reqm :repositories repositories))]
       (if (-> opts :print :title)
         (print/print-title "COLLECTING DEPENDENCIES")
         (clojure.core/print "n"))
       (-> (.collectDependencies system session request)
           (result/return-deps @listener/*progress* opts))))))
link
(collect-dependencies '[prismatic/schema "1.1.3"] {:type :coord}) => '[[prismatic/schema "1.1.3"]]

deploy-artifact ^

deploys artifacts to the given coordinate

v 3.0
(defn deploy-artifact
  ([coord {:keys [artifacts repository] :as opts}]
   (deploy-artifact (base/aether) coord opts))
  ([{:keys [system session]} coord {:keys [artifacts repository] :as opts}]
   (binding [listener/*progress* (atom [])
             listener/*pairs* (atom {})]
     (let [opts   (nested/merge-nested {:type :default
                                        :print {:title true
                                                :timing true}}
                                       opts)
           opts (populate-artifact coord opts)
           request (request/deploy-request opts)]
       (if (-> opts :print :title)
         (print/print-title "DEPLOYING ARTIFACTS")
         (clojure.core/print "n"))
       (-> (.deploy system session request)
           (result/return @listener/*progress* opts))))))
link
(deploy-artifact '[hara/hara.module.artifact "2.4.8"] {:artifacts [{:file "hara.module.artifact-2.4.8.jar" :extension "jar"} {:file "hara.module.artifact-2.4.8.pom" :extension "pom"} {:file "hara.module.artifact-2.4.8.pom.asc" :extension "pom.asc"} {:file "hara.module.artifact-2.4.8.jar.asc" :extension "jar.asc"}] :repository {:id "clojars" :url "https://clojars.org/repo/" :authentication {:username "zcaudate" :password "hello"}}})

install-artifact ^

installs artifacts to the given coordinate

v 3.0
(defn install-artifact
  ([coord {:keys [artifacts] :as opts}]
   (install-artifact (base/aether) coord opts))
  ([{:keys [system session]} coord {:keys [artifacts] :as opts}]
   (binding [listener/*progress* (atom [])
             listener/*pairs* (atom {})]
     (let [opts   (nested/merge-nested {:type :default
                                        :print {:title true
                                                :timing true}}
                                       opts)
           opts (populate-artifact coord opts)
           request (request/install-request opts)]
       (if (-> opts :print :title)
         (print/print-title "INSTALLING ARTIFACTS")
         (clojure.core/print "n"))
       (-> (.install system session request)
           (result/return @listener/*progress* opts))))))
link
(install-artifact '[im.chit/hara.module.artifact "2.4.8"] {:artifacts [{:file "hara.module.artifact-2.4.8.jar" :extension "jar"} {:file "hara.module.artifact-2.4.8.pom" :extension "pom"}]})

outdated? ^

checks if a set of artifacts are outdated

v 3.0
(defn outdated?
  ([coords]
   (outdated? coords {}))
  ([coords opts]
   (outdated? (base/aether) coords opts))
  ([aether coords opts]
   (let [opts    (nested/merge-nested opts {:print {:results true}})
         reps    (mapv artifact/artifact coords)
         inputs  (map #(assoc % :version "LATEST") reps)
         latest  (resolve-versions aether inputs opts)
         results (->> (mapv (fn [in new]
                              (if (not= (:version in)
                                        (:version new))
                                [(first (artifact/artifact :coord in)) (:version in)  '=> (:version new)]))
                            reps latest)
                      (filterv identity))]
     (cond-> results
       (and (seq results) (-> opts :print :results)) (doto prn)))))
link
(outdated? '[[binaryage/devtools "0.9.7"]]) => (contains-in [['binaryage/devtools "0.9.7" '=> string?]])

populate-artifact ^

allows coordinate to fill rest of values

v 3.0
(defn populate-artifact
  [coord opts]
  (let [root (-> (artifact/artifact coord)
                 (select-keys [:artifact :group :version]))]
    opts (update-in opts [:artifacts]
                    (fn [arr] (mapv #(merge % root) arr)))))
link
(populate-artifact '[midje "1.6.3"] {:artifacts [{:extension "pom" :file "midje.pom"} {:extension "jar" :file "midje.jar"}]}) => {:artifacts [{:extension "pom", :file "midje.pom", :artifact "midje", :group "midje", :version "1.6.3"} {:extension "jar", :file "midje.jar", :artifact "midje", :group "midje", :version "1.6.3"}]}

pull ^

resolves the coordinate from maven and loads dependency into classpath

v 3.0
(defn pull
  ([coords]
   (pull coords {}))
  ([coords opts]
   (pull (base/aether) coords opts))
  ([{:keys [loader] :as aether} coords {:keys [keep renew nodeps] :as opts}]
   (let [loader    (or loader classloader/+base+)
         coords    (if (or (not (vector? coords))
                           (artifact/coord? coords))
                     [coords]
                     coords)
         coords    (if-not renew (remove #(deps/loaded-artifact? % loader) coords))
         coords    (if nodeps
                     coords
                     (resolve-dependencies aether coords {:print {:hierarchy false}}))
         unloaded  (if-not keep (deps/unload coords loader :different))
         loaded    (deps/load coords loader)]
     {:artifacts coords
      :unloaded unloaded
      :loaded loaded})))
link
(pull '[[joda-time "2.9"]])

push ^

gets rid of a dependency that is not needed

v 3.0
(defn push
  ([coords]
   (push coords {}))
  ([coords opts]
   (push (base/aether) coords opts))
  ([{:keys [loader] :as aether} coords {:keys [clean simulate nodeps] :as opts}]
   (let [loader  (or loader classloader/+base+)
         coords    (if (or (not (vector? coords))
                           (artifact/coord? coords))
                     [coords]
                     coords)
         coords  (if nodeps
                   coords
                   (collect-dependencies aether coords {:return :resolved
                                                        :print {:hierarchy false}}))
         unloaded (if-not simulate (deps/unload coords loader :same))
         cleaned  (mapcat (fn [coord]
                            (case clean
                              :none     nil
                              :artifact (deps/clean coord (assoc opts :full false))
                              :full     (deps/clean coord (assoc opts :full true))
                              nil))
                          coords)]
     {:artifacts coords
      :unloaded unloaded
      :cleaned cleaned})))
link
(push '[[joda-time "2.9"]])

resolve-dependencies ^

resolves maven dependencies for a set of coordinates

v 3.0
(defn resolve-dependencies
  ([coords]
   (resolve-dependencies coords {}))
  ([coords opts]
   (resolve-dependencies (base/aether) coords opts))
  ([{:keys [system session repositories]} coords opts]
   (binding [listener/*progress* (atom [])
             listener/*pairs* (atom {})]
     (let [opts   (nested/merge-nested {:type :default
                                        :return :resolved
                                        :print {:hierarchy true
                                                :title true
                                                :timing true}}
                                       opts)
           reqm   (cond (and (sequential? coords)
                             (not (artifact/coord? coords)))
                        {:dependencies (mapv artifact->dependency coords)}

                        :else
                        {:root (artifact->dependency coords)})
           request (request/dependency-request
                    (assoc reqm :repositories repositories))]
       (if (-> opts :print :title)
         (print/print-title "RESOLVING DEPENDENCIES")
         (clojure.core/print "n"))
       (-> (.resolveDependencies system session request)
           (result/return-deps @listener/*progress* opts))))))
link
(resolve-dependencies '[prismatic/schema "1.1.3"] {:type :coord}) => '[[prismatic/schema "1.1.3"]] (vec (sort (resolve-dependencies '[midje "1.6.3"] {:type :coord}))) => '[[clj-time/clj-time "0.6.0"] [colorize/colorize "0.1.1"] [commons-codec/commons-codec "1.9"] [dynapath/dynapath "0.2.0"] [gui-diff/gui-diff "0.5.0"] [joda-time/joda-time "2.2"] [midje/midje "1.6.3"] [net.cgrand/parsley "0.9.1"] [net.cgrand/regex "1.1.0"] [ordered/ordered "1.2.0"] [org.clojars.trptcolin/sjacket "0.1.3"] [org.clojure/core.unify "0.5.2"] [org.clojure/math.combinatorics "0.0.7"] [org.clojure/tools.macro "0.1.5"] [org.clojure/tools.namespace "0.2.4"] [slingshot/slingshot "0.10.3"] [swiss-arrows/swiss-arrows "1.0.0"] [utilize/utilize "0.2.3"]]

resolve-versions ^

checks for given version of artifacts

v 3.0
(defn resolve-versions
  ([coords]
   (resolve-versions coords {}))
  ([coords opts]
   (resolve-versions (base/aether) coords opts))
  ([{:keys [system session repositories]} coords opts]
   (binding [listener/*progress* (atom [])
             listener/*pairs* (atom {})]
     (let [opts   (nested/merge-nested {:type :default
                                        :print {:title true
                                                :timing true}}
                                       opts)]
       (if (-> opts :print :title)
         (print/print-title "RESOLVE VERSIONS")
         (clojure.core/print "n"))
       (-> (keep (fn [coord]
                   (let [request (request/version-request {:artifact (artifact/artifact coord)
                                                           :repositories repositories})]
                     (try (.resolveVersion system session request)
                          (catch Throwable t
                            (println "Not Resolved:" coord)))))
                 coords)
           (result/return @listener/*progress* opts))))))
link
(resolve-versions '[[lein-monolith "LATEST"] [org.clojure/clojure "LATEST"]]) => (contains-in [{:group "lein-monolith", :artifact "lein-monolith", :version string?} {:group "org.clojure", :artifact "clojure", :version string?}])