Skip to content

Commit

Permalink
Allow depedency-hierarchy to match snapshots and version ranges
Browse files Browse the repository at this point in the history
dependency-hierarchy would not return all the dependencies when
passing it the same specs used to resolve-depenedncies if there
was a snapshot or version range.

Add within? method to do comparisions instead of select-keys or =.
  • Loading branch information
xeqi committed Apr 5, 2012
1 parent 0c68c6c commit c15a1f7
Show file tree
Hide file tree
Showing 28 changed files with 244 additions and 14 deletions.
67 changes: 63 additions & 4 deletions src/main/clojure/cemerick/pomegranate/aether.clj
Expand Up @@ -18,7 +18,8 @@
(org.sonatype.aether.util.graph PreorderNodeListGenerator)
(org.sonatype.aether.util.artifact DefaultArtifact SubArtifact)
(org.sonatype.aether.deployment DeployRequest)
(org.sonatype.aether.installation InstallRequest)))
(org.sonatype.aether.installation InstallRequest)
(org.sonatype.aether.util.version GenericVersionScheme)))

(def ^{:private true} default-local-repo
(io/file (System/getProperty "user.home") ".m2" "repository"))
Expand Down Expand Up @@ -202,6 +203,11 @@
(:classifier opts "*")
(:extension opts "*")))

(defn- normalize-exclusion-spec [spec]
(if (symbol? spec)
[spec]
spec))

(defn- dependency
[[group-artifact version & {:keys [scope optional exclusions]
:as opts
Expand All @@ -211,7 +217,7 @@
(Dependency. (DefaultArtifact. (coordinate-string dep-spec))
scope
optional
(map (comp exclusion #(if (symbol? %) [%] %)) exclusions)))
(map (comp exclusion normalize-exclusion-spec) exclusions)))

(declare dep-spec*)

Expand Down Expand Up @@ -408,13 +414,66 @@ kwarg to the repository kwarg.
[graph]
(->> graph keys (map (comp :file meta)) (remove nil?)))

(defn- exclusion= [spec1 spec2]
(let [[dep & opts] (normalize-exclusion-spec spec1)
[sdep & sopts] (normalize-exclusion-spec spec2)
om (apply hash-map opts)
som (apply hash-map sopts)]
(and (= (group dep)
(group sdep))
(= (name dep)
(name sdep))
(= (:extension om "*")
(:extension som "*"))
(= (:classifier om "*")
(:classifier som "*"))
spec2)))

(defn- exclusions-match? [excs sexcs]
(if-let [ex (first excs)]
(if-let [match (some (partial exclusion= ex) sexcs)]
(recur (next excs) (remove #{match} sexcs))
false)
(empty? sexcs)))

(defn within? [[dep version & opts] [sdep sversion & sopts]]
"Determines if the first coordinate would be a version in the second
coordinate. The first coordinate is not allowed to contain a
version range."
(let [om (apply hash-map opts)
som (apply hash-map sopts)]
(and (= (group dep)
(group sdep))
(= (name dep)
(name sdep))
(= (:extension om "jar")
(:extension som "jar"))
(= (:classifier om)
(:classifier som))
(= (:scope om "compile")
(:scope som "compile"))
(= (:optional om false)
(:optional som false))
(exclusions-match? (:exclusions om) (:exclusions som))
(or (= version sversion)
(if-let [[_ ver] (re-find #"^(.*)-SNAPSHOT$" sversion)]
(re-find (re-pattern (str "^" ver "-\\d+\\.\\d+-\\d+$"))
version)
(let [gsv (GenericVersionScheme.)
vc (.parseVersionConstraint gsv sversion)
v (.parseVersion gsv version)]
(.containsVersion vc v)))))))

(defn dependency-hierarchy
"Returns a dependency hierarchy based on the provided dependency graph
(as returned by `resolve-dependencies`) and the coordinates that should
be the root(s) of the hierarchy. Siblings are sorted alphabetically."
[root-coordinates dep-graph]
(let [hierarchy (for [[root children] (select-keys dep-graph (map (comp dep-spec dependency) root-coordinates))]
[root (dependency-hierarchy children dep-graph)])]
(let [root-specs (map (comp dep-spec dependency) root-coordinates)
hierarchy (for [root (filter
#(some (fn [root] (within? % root)) root-specs)
(keys dep-graph))]
[root (dependency-hierarchy (dep-graph root) dep-graph)])]
(when (seq hierarchy)
(into (sorted-map-by #(apply compare (map coordinate-string %&))) hierarchy))))

115 changes: 114 additions & 1 deletion src/test/clojure/cemerick/pomegranate/aether_test.clj
Expand Up @@ -111,10 +111,123 @@
:local-repo tmp-local-repo-dir)
(is (= 3 (count (.list (io/file tmp-local-repo-dir "group" "artifact" "1.0.0"))))))

(deftest within?-comparisons
(is (aether/within? '[demo "0.0.1"]
'[demo "0.0.1"]))
(is (aether/within? '[demo "0.0.1"]
'[demo/demo "0.0.1"]))
(is (aether/within? '[demo/demo "0.0.1"]
'[demo "0.0.1"]))
(is (aether/within? '[demo "0.0.1"]
'[demo "[0.0.1,2.0.0)"]))
(is (not (aether/within? '[demo "2.0.0"]
'[demo "[0.0.1,2.0.0)"])))
(is (not (aether/within? '[demo "0.0.1"]
'[demo "(0.0.1,2.0.0)"])))
(is (aether/within? '[demo "0.0.1-SNAPSHOT"]
'[demo/demo "0.0.1-SNAPSHOT"]))
(is (aether/within? '[demo "0.0.1-SNAPSHOT"]
'[demo "0.0.1-SNAPSHOT"]))
(is (aether/within? '[demo "0.0.1-20120403.012847-1"]
'[demo "0.0.1-SNAPSHOT"]))
(is (not (aether/within? '[demo "0.0.1-SNAPSHOT"]
'[demo "0.0.1-20120403.012847-10"])))
(is (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :extension "jar"]))
(is (aether/within? '[demo "0.0.1" :extension "jar"]
'[demo "0.0.1"]))
(is (not (aether/within? '[demo "0.0.1" :extension "pom"]
'[demo "0.0.1"])))
(is (not (aether/within? '[demo "0.0.1"]
'[demo "0.0.1":extension "pom"])))
(is (aether/within? '[demo "0.0.1" :classifier "sources"]
'[demo "0.0.1" :classifier "sources"]))
(is (not (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :classifier "sources"])))
(is (not (aether/within? '[demo "0.0.1" :classifier "sources"]
'[demo "0.0.1"])))
(is (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :scope "compile"]))
(is (aether/within? '[demo "0.0.1" :scope "compile"]
'[demo "0.0.1"]))
(is (aether/within? '[demo "0.0.1" :scope "compile"]
'[demo "0.0.1" :scope "compile"]))
(is (not (aether/within? '[demo "0.0.1" :scope "compile"]
'[demo "0.0.1" :scope "test"])))
(is (not (aether/within? '[demo "0.0.1" :scope "test"]
'[demo "0.0.1" :scope "compile"])))
(is (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :optional false]))
(is (aether/within? '[demo "0.0.1" :optional false]
'[demo "0.0.1"]))
(is (aether/within? '[demo "0.0.1" :optional true]
'[demo "0.0.1" :optional true]))
(is (not (aether/within? '[demo "0.0.1" :optional true]
'[demo "0.0.1"])))
(is (not (aether/within? '[demo "0.0.1"]
'[demo "0.0.1":optional true])))
(is (aether/within? '[demo "0.0.1" :exclusions []]
'[demo "0.0.1"]))
(is (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :exclusions []]))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo2]]]
'[demo "0.0.1" :exclusions [[demo2]]]))
(is (not (aether/within? '[demo "0.0.1" :exclusions [[demo2]]]
'[demo "0.0.1"])))
(is (not (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :exclusions [[demo2]]])))
(is (not (aether/within? '[demo "0.0.1" :exclusions [demo2]]
'[demo "0.0.1"])))
(is (not (aether/within? '[demo "0.0.1"]
'[demo "0.0.1" :exclusions [demo2]])))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo2]
[demo3]]]
'[demo "0.0.1" :exclusions [[demo2]
[demo3]]]))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo3]
[demo2]]]
'[demo "0.0.1" :exclusions [[demo2]
[demo3]]]))
(is (not (aether/within? '[demo "0.0.1" :exclusions [[demo2]]]
'[demo "0.0.1" :exclusions [[demo2]
[demo3]]])))
(is (not (aether/within? '[demo "0.0.1" :exclusions [[demo2]
[demo3]]]
'[demo "0.0.1" :exclusions [[demo2]]])))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo2]]]
'[demo "0.0.1" :exclusions [[demo2 :classifier "*"]]]))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo2 :classifier "*"]]]
'[demo "0.0.1" :exclusions [[demo2]]]))
(is (not (aether/within?
'[demo "0.0.1" :exclusions [[demo2 :classifier "*"]]]
'[demo "0.0.1" :exclusions [[demo2 :classifier "sources"]]])))
(is (not (aether/within?
'[demo "0.0.1" :exclusions [[demo2 :classifier "sources"]]]
'[demo "0.0.1" :exclusions [[demo2 :classifier "*"]]])))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo2]]]
'[demo "0.0.1" :exclusions [[demo2 :extension "*"]]]))
(is (aether/within? '[demo "0.0.1" :exclusions [[demo2 :extension "*"]]]
'[demo "0.0.1" :exclusions [[demo2]]]))
(is (not (aether/within?
'[demo "0.0.1" :exclusions [[demo2 :extension "*"]]]
'[demo "0.0.1" :exclusions [[demo2 :extension "jar"]]])))
(is (not (aether/within?
'[demo "0.0.1" :exclusions [[demo2 :extension "jar"]]]
'[demo "0.0.1" :exclusions [[demo2 :extension "*"]]]))))

(deftest dependency-hierarchy-matching
(let [coords '[[demo/demo2 "[0.0.1,2.0.0)"]
[tester "0.1.0-SNAPSHOT"]]
deps (aether/resolve-dependencies
:repositories test-repo
:coordinates coords
:local-repo tmp-local-repo-dir)]
(is (= {['demo/demo2 "1.0.0"] {['demo "1.0.0"] nil}
['tester "0.1.0-20120403.012847-1"] nil}
(aether/dependency-hierarchy coords deps)))))

(comment
"tests needed for:
repository authentication
repository policies
dependency options (scope/optional)
Expand Down
1 change: 1 addition & 0 deletions test-repo/demo/demo/1.0.0/demo-1.0.0.jar.md5
@@ -0,0 +1 @@
d41d8cd98f00b204e9800998ecf8427e
2 changes: 1 addition & 1 deletion test-repo/demo/demo/1.0.0/demo-1.0.0.jar.sha1
@@ -1 +1 @@
da39a3ee5e6b4b0d3255bfef95601890afd80709
da39a3ee5e6b4b0d3255bfef95601890afd80709
1 change: 1 addition & 0 deletions test-repo/demo/demo/1.0.0/demo-1.0.0.pom.md5
@@ -0,0 +1 @@
5689f1eaf926240885eb9976e5269e5d
2 changes: 1 addition & 1 deletion test-repo/demo/demo/1.0.0/demo-1.0.0.pom.sha1
@@ -1 +1 @@
eb4ff44542c69c5271390dad76a96bfd15b4858a
eb4ff44542c69c5271390dad76a96bfd15b4858a
Expand Up @@ -2,11 +2,11 @@
<metadata>
<groupId>demo</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
<versioning>
<release>1.0.0</release>
<versions>
<version>1.0.0</version>
</versions>
<lastUpdated>20111120005849</lastUpdated>
<lastUpdated>20120403044818</lastUpdated>
</versioning>
</metadata>
1 change: 1 addition & 0 deletions test-repo/demo/demo/maven-metadata.xml.md5
@@ -0,0 +1 @@
eba3d5db3eae4a0d224883479f0af51a
1 change: 1 addition & 0 deletions test-repo/demo/demo/maven-metadata.xml.sha1
@@ -0,0 +1 @@
e135fe7f1f28125dc0ed279af92e112af16bcf64
1 change: 1 addition & 0 deletions test-repo/demo/demo2/1.0.0/demo2-1.0.0.jar.md5
@@ -0,0 +1 @@
d41d8cd98f00b204e9800998ecf8427e
2 changes: 1 addition & 1 deletion test-repo/demo/demo2/1.0.0/demo2-1.0.0.jar.sha1
@@ -1 +1 @@
da39a3ee5e6b4b0d3255bfef95601890afd80709
da39a3ee5e6b4b0d3255bfef95601890afd80709
1 change: 1 addition & 0 deletions test-repo/demo/demo2/1.0.0/demo2-1.0.0.pom.md5
@@ -0,0 +1 @@
79893caa8e0888232ed9dfe56e396172
2 changes: 1 addition & 1 deletion test-repo/demo/demo2/1.0.0/demo2-1.0.0.pom.sha1
@@ -1 +1 @@
d2a795ccaccf9ade57f7938c390368eeb2e842e7
d2a795ccaccf9ade57f7938c390368eeb2e842e7
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>demo</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
<artifactId>demo2</artifactId>
<versioning>
<release>1.0.0</release>
<versions>
<version>1.0.0</version>
</versions>
<lastUpdated>20111120005849</lastUpdated>
<lastUpdated>20120403045648</lastUpdated>
</versioning>
</metadata>
1 change: 1 addition & 0 deletions test-repo/demo/demo2/maven-metadata.xml.md5
@@ -0,0 +1 @@
8550a6918ed8fe0cf9ff6e08e61c4d8c
1 change: 1 addition & 0 deletions test-repo/demo/demo2/maven-metadata.xml.sha1
@@ -0,0 +1 @@
c38f519e44c887aa563201af58779379cbee4b18
25 changes: 25 additions & 0 deletions test-repo/tester/tester/0.1.0-SNAPSHOT/maven-metadata.xml
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>tester</groupId>
<artifactId>tester</artifactId>
<version>0.1.0-SNAPSHOT</version>
<versioning>
<snapshot>
<timestamp>20120403.012847</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
<lastUpdated>20120403012847</lastUpdated>
<snapshotVersions>
<snapshotVersion>
<extension>jar</extension>
<value>0.1.0-20120403.012847-1</value>
<updated>20120403012847</updated>
</snapshotVersion>
<snapshotVersion>
<extension>pom</extension>
<value>0.1.0-20120403.012847-1</value>
<updated>20120403012847</updated>
</snapshotVersion>
</snapshotVersions>
</versioning>
</metadata>
@@ -0,0 +1 @@
32f77845f3013e9010130dd3c5056d35
@@ -0,0 +1 @@
34f980dd6a45ef4ad423c27315015580f5e8c996
Binary file not shown.
@@ -0,0 +1 @@
b959415ced8425a03218a51430d8a7e1
@@ -0,0 +1 @@
ecddbf891119b76b09e0f888f8cf5764932c811b
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><groupId>tester</groupId><artifactId>tester</artifactId><version>0.1.0-SNAPSHOT</version><name>tester</name><description>FIXME: write description</description><url>http://example.com/FIXME</url><licenses><license><name>Eclipse Public License</name><url>http://www.eclipse.org/legal/epl-v10.html</url></license></licenses><build><sourceDirectory>/workspace/tester/src</sourceDirectory><testSourceDirectory>/workspace/tester/test</testSourceDirectory><resources><resource><directory>/workspace/tester/resources</directory></resource></resources><testResources><testResource><directory>/workspace/tester/resources</directory></testResource></testResources></build><repositories><repository><id>central</id><url>http://repo1.maven.org/maven2</url></repository><repository><id>clojars</id><url>http://clojars.org/repo/</url></repository><repository><id>snapshots</id><url>file:///tmp/snapshots</url></repository></repositories><dependencies></dependencies></project>
<!-- This file was autogenerated by Leiningen.
Please do not edit it directly; instead edit project.clj and regenerate it.
It should not be considered canonical data. For more information see
https://github.com/technomancy/leiningen -->

@@ -0,0 +1 @@
f5550306172f01752d6483dd88528271
@@ -0,0 +1 @@
eb42a597bcb2ec429e5ba36ed9b16100a1e9a336
11 changes: 11 additions & 0 deletions test-repo/tester/tester/maven-metadata.xml
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>tester</groupId>
<artifactId>tester</artifactId>
<versioning>
<versions>
<version>0.1.0-SNAPSHOT</version>
</versions>
<lastUpdated>20120403012847</lastUpdated>
</versioning>
</metadata>
1 change: 1 addition & 0 deletions test-repo/tester/tester/maven-metadata.xml.md5
@@ -0,0 +1 @@
0748c7d4b7b9b6dc951840d798be8fda
1 change: 1 addition & 0 deletions test-repo/tester/tester/maven-metadata.xml.sha1
@@ -0,0 +1 @@
23c0ae6c73dc4c080e18d7664a88e9d6936b9521

0 comments on commit c15a1f7

Please sign in to comment.