Created
August 1, 2011 04:52
-
-
Save ato/1117588 to your computer and use it in GitHub Desktop.
mucking with Aether
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Maven hoopla | |
(defproject moopla "1.0.0-SNAPSHOT" | |
:dependencies [[org.clojure/clojure "1.2.0"] | |
[org.clojure/clojure-contrib "1.2.0"] | |
;; Dependency hoops! | |
[org.sonatype.aether/aether-api "1.8"] | |
[org.sonatype.aether/aether-util "1.8"] | |
[org.sonatype.aether/aether-impl "1.8"] | |
[org.sonatype.aether/aether-connector-wagon "1.8" | |
:exclusions [commons-logging/commons-logging-api log4j junit | |
org.codehaus.plexus/plexus-container-default]] | |
[org.apache.maven/maven-aether-provider "3.0.1"] | |
[org.apache.maven.wagon/wagon-file "1.0-beta-7"] | |
[org.apache.maven.wagon/wagon-http-lightweight "1.0-beta-7" | |
:exclusions [commons-logging nekohtml | |
nekohtml/xercesMinimal]]]) | |
(ns moopla.core | |
(:import org.apache.maven.repository.internal.DefaultServiceLocator | |
org.apache.maven.repository.internal.MavenRepositorySystemSession | |
org.apache.maven.wagon.providers.file.FileWagon | |
org.apache.maven.wagon.providers.http.LightweightHttpWagon | |
org.sonatype.aether.RepositorySystem | |
org.sonatype.aether.artifact.Artifact | |
org.sonatype.aether.collection.CollectRequest | |
org.sonatype.aether.connector.wagon.WagonProvider | |
org.sonatype.aether.connector.wagon.WagonRepositoryConnectorFactory | |
org.sonatype.aether.graph.Dependency | |
org.sonatype.aether.graph.DependencyNode | |
org.sonatype.aether.graph.Exclusion | |
org.sonatype.aether.repository.ArtifactRepository | |
org.sonatype.aether.repository.LocalRepository | |
org.sonatype.aether.repository.RemoteRepository | |
org.sonatype.aether.resolution.ArtifactRequest | |
org.sonatype.aether.resolution.MetadataRequest | |
org.sonatype.aether.spi.connector.RepositoryConnectorFactory | |
org.sonatype.aether.util.artifact.DefaultArtifact)) | |
(def ^{:dynamic true} *wagons* | |
{"file" #(FileWagon.) | |
"http" #(LightweightHttpWagon.)}) | |
(def ^{:dynamic true} *local-repository* | |
(str (System/getProperty "user.home") "/.m2/repository")) | |
(def ^{:dynamic true} *default-repositories* | |
[["clojars" "http://clojars.org/repo"]]) | |
(def wagon-provider (reify WagonProvider | |
(lookup [this role] ((*wagons* role))) | |
(release [this wagon]))) | |
(defn repo-system | |
{:tag org.sonatype.aether.RepositorySystem} | |
([] (-> (doto (DefaultServiceLocator.) | |
(.setServices WagonProvider (to-array [wagon-provider])) | |
(.addService RepositoryConnectorFactory | |
WagonRepositoryConnectorFactory)) | |
(.getService RepositorySystem)))) | |
(defn repo-session | |
{:tag org.sonatype.aether.RepositorySystemSession} | |
([] (repo-session (repo-system))) | |
([system] | |
(doto (MavenRepositorySystemSession.) | |
(.setLocalRepositoryManager | |
(.newLocalRepositoryManager | |
system (LocalRepository. *local-repository*)))))) | |
(def ^{:dynamic true} *system* (repo-system)) | |
(def ^{:dynamic true} *session* (repo-session *system*)) | |
(defn- parse-lein-artifact | |
"Parse a Leiningen-style artifact vector returning a map. | |
[group-id/artifact-id \"version\" & [:option value ...]]" | |
[coords] | |
(let [[id version & opts] coords] | |
(assoc (apply hash-map opts) | |
:group-id (when (instance? clojure.lang.Named id) (namespace id)) | |
:artifact-id (name id) | |
:version version))) | |
(defn ^Artifact make-artifact | |
"Create an Aether Artifact object. The coords may be a Maven-style coordinates | |
string \"groupId:artifactId[:extension[:classifier]]:version\", a | |
Leiningen-style vector [group-id/artifact-id \"version\" & opts] or a map | |
containing the keys :group-id, :artifact-id, :extension, :classifier and | |
:version." | |
([group-id artifact-id version] | |
(make-artifact {:group-id group-id | |
:artifact-id artifact-id | |
:version version})) | |
([coords] | |
(cond (instance? Artifact coords) coords | |
(string? coords) (DefaultArtifact. ^String coords) | |
(vector? coords) (recur (parse-lein-artifact coords)) | |
:else (DefaultArtifact. | |
(or (:group-id coords) (:artifact-id coords)) | |
(:artifact-id coords) | |
(:classifier coords "") | |
(:extension coords "jar") | |
(:version coords))))) | |
(defn ^Exclusion make-exclusion | |
"Create an Aether Exclusion object. The coords may be a Leiningen-style | |
vector [group-id/artifact-id & opts], a symbol group-id/symbol-id or a | |
map containing the keys :group-id, :artifact-id, :extension and :classifier." | |
([group-id artifact-id] | |
(make-exclusion {:group-id group-id, :artifact-id artifact-id})) | |
([coords] | |
(cond (instance? Exclusion coords) coords | |
(symbol? coords) (recur [coords]) | |
(vector? coords) (let [[id & opts] coords] | |
(recur (assoc (apply hash-map opts) | |
:group-id (namespace id) | |
:artifact-id (name id)))) | |
:else (Exclusion. | |
(or (:group-id coords) (:artifact-id coords)) | |
(:artifact-id coords) | |
(:extension coords) | |
(:classifier coords))))) | |
(defn ^Dependency make-dependency | |
"Creates an Aether Dependency object. The coords may be one of the types | |
accepted by moopla.core/artifact with the additional options: | |
:scope scope of the dependency (eg \"compile\") | |
:optional? is this an optional dependency? (boolean) | |
:exclusions seq of artifacts to exclude from transitive | |
dependencies (see moopla.core/dependency)" | |
([group-id artifact-id version] | |
(make-dependency (make-artifact group-id artifact-id version))) | |
([coords] | |
(cond | |
(instance? Dependency coords) coords | |
(vector? coords) (recur (parse-lein-artifact coords)) | |
(associative? coords) (Dependency. | |
(make-artifact coords) | |
(:scope coords) | |
(boolean (:optional? coords false)) | |
(map make-exclusion (:exclusions coords))) | |
:else (Dependency. (make-artifact coords) nil)))) | |
(defn ^ArtifactRepository make-repository | |
"Create an Aether ArtifactRepository object. | |
The settings may be a map of the options below or a Leiningen-style | |
[id url] or a [id settings] vector. | |
Options: | |
:id unique repository idenitifier | |
:url URL of the repository | |
:snapshots? contains snapshots versions? | |
:releases? contains release versions? | |
:proxy proxy settings | |
:authentication authentication settings" | |
([id url] (make-repository {:id id :url url})) | |
([settings] | |
(cond | |
(instance? ArtifactRepository settings) settings | |
(vector? settings) (let [[id url] settings] | |
(if (associative? url) | |
(recur (assoc (into {} url) :id id)) | |
(recur {:id id :url url}))) | |
:else (doto (RemoteRepository. (:id settings) | |
(:type settings "default") | |
(str (:url settings))) | |
(.setProxy (:proxy settings)) | |
(.setAuthentication (:authentication settings)) | |
(.setPolicy true (:snapshots? settings)) | |
(.setPolicy false (:releases? settings)))))) | |
(defn ^java.io.File resolve-artifact | |
"Resolves the local path for an artifact. The artifact will be downloaded to | |
the local repository if necessary." | |
([artifact] (resolve-artifact artifact *default-repositories*)) | |
([artifact repositories] | |
(let [request (ArtifactRequest. (make-artifact artifact) | |
(map make-repository repositories) | |
nil)] | |
(-> (.resolveArtifact *system* *session* request) | |
(.getArtifact) | |
(.getFile))))) | |
(defn resolve-deps | |
"Collects all the transitive dependencies for an artifact and resolves them to | |
local paths. The artifacts will be downloaded to the local repository as | |
necessary." | |
([artifact] (resolve-deps artifact *default-repositories*)) | |
([artifact repositories] | |
(let [request (CollectRequest. (make-dependency artifact) | |
(map make-repository repositories))] | |
(for [result (.resolveDependencies *system* *session* request nil)] | |
(.getFile (.getArtifact result)))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment