Skip to content
Browse files

Merge pull request #1 from hugoduncan/feature/improvements

Feature/improvements
  • Loading branch information...
2 parents d2cf2aa + 930bb4c commit 73bdcba02d2932c388665bc4dcc0325cd28f1259 @Raynes Raynes committed Feb 12, 2012
Showing with 68 additions and 31 deletions.
  1. +2 −1 .gitignore
  2. +3 −1 project.clj
  3. +47 −26 src/bultitude/core.clj
  4. +16 −3 test/bultitude/core_test.clj
View
3 .gitignore
@@ -2,4 +2,5 @@ pom.xml
*jar
/lib/
/classes/
-.lein-deps-sum
+.lein-deps-sum
+.lein-failures
View
4 project.clj
@@ -1,3 +1,5 @@
(defproject bultitude "0.1.1"
:description "A library for find Clojure namespaces on the classpath."
- :dependencies [[clojure "1.3.0"]])
+ :dependencies [[clojure "1.2.1"]]
+ :multi-deps {"1.3.0" [[org.clojure/clojure "1.3.0"]]
+ "1.4.0" [[org.clojure/clojure "1.4.0-beta1"]]})
View
73 src/bultitude/core.clj
@@ -50,36 +50,58 @@
(defn- split-classpath [classpath]
(.split classpath (System/getProperty "path.separator")))
-(defn- classpath-files
- "A seq of all files on the classpath."
- []
- (let [cl (.getContextClassLoader (Thread/currentThread))]
- (concat (when (instance? DynamicClassLoader cl)
- (.getURLs cl))
- (split-classpath (System/getProperty "java.class.path")))))
+(defn loader-classpath
+ "Returns a sequence of File paths from a classloader."
+ [loader]
+ (when (instance? java.net.URLClassLoader loader)
+ (map
+ #(java.io.File. (.getPath ^java.net.URL %))
+ (.getURLs ^java.net.URLClassLoader loader))))
+
+(defn classpath-files
+ "Returns a sequence of File objects of the elements on the classpath."
+ ([classloader]
+ (distinct
+ (mapcat
+ loader-classpath
+ (take-while
+ identity
+ (iterate #(.getParent %) classloader)))))
+ ([] (classpath-files (clojure.lang.RT/baseLoader))))
+
+(defn- classpath->collection [classpath]
+ (if (coll? classpath)
+ classpath
+ (split-classpath classpath)))
(defn- classpath->files [classpath]
- (map io/file (if (coll? classpath)
- classpath
- (split-classpath classpath))))
+ (map io/file classpath))
+
+(defn file->namespaces
+ "Map a classpath file to the namespaces it contains. `prefix` allows for
+ reducing the namespace search space. For large directories on the classpath,
+ passing a `prefix` can provide significant efficiency gains."
+ [prefix f]
+ (cond
+ (.isDirectory f) (namespaces-in-dir
+ (if prefix
+ (io/file f (.replaceAll prefix "\\." "/"))
+ f))
+ (jar? f) (let [ns-list (namespaces-in-jar f)]
+ (if prefix
+ (filter #(and % (.startsWith (name %) prefix)) ns-list)
+ ns-list))))
(defn namespaces-on-classpath
- "Return all namespaces matching the given prefix both on disk and
- inside jar files. If :prefix is passed, only return namespaces that
- begin with this prefix. If :classpath is passed, it should be a seq
- of File objects or a classpath string. If it is not passed, default
- to java.class.path and the current classloader, assuming it is a
- dynamic classloader."
+ "Return symbols of all namespaces matching the given prefix both on disk and
+ inside jar files. If :prefix is passed, only return namespaces that begin with
+ this prefix. If :classpath is passed, it should be a seq of File objects or a
+ classpath string. If it is not passed, default to java.class.path and the
+ current classloader, assuming it is a dynamic classloader."
[& {:keys [prefix classpath] :or {classpath (classpath-files)}}]
- (let [classpath (classpath->files classpath)]
- (concat (mapcat namespaces-in-dir
- (for [dir classpath
- :when (.isDirectory dir)]
- (io/file dir (if prefix (.replaceAll prefix "\\." "/") ""))))
- (let [jars (mapcat namespaces-in-jar (filter jar? classpath))]
- (if prefix
- (filter #(and % (.startsWith (name %) prefix)) jars)
- jars)))))
+ (mapcat
+ (partial file->namespaces prefix)
+ (-> classpath classpath->collection classpath->files)))
(defn path-for
"Transform a namespace into a .clj file path relative to classpath root."
@@ -88,4 +110,3 @@
(.replace \- \_)
(.replace \. \/))
".clj"))
-
View
19 test/bultitude/core_test.clj
@@ -2,6 +2,19 @@
(:use clojure.test
bultitude.core))
-(deftest a-test
- (testing "FIXME, I fail."
- (is (= 0 1))))
+(deftest namespaces-on-classpath-test
+ (testing "find clojure.core"
+ (is (seq (filter
+ #(= 'clojure.core %)
+ (namespaces-on-classpath)))))
+ (testing "prefix"
+ (is (seq (filter
+ #(= 'clojure.core %)
+ (namespaces-on-classpath :prefix "clojure.core"))))
+ (is (every?
+ #(.startsWith (name %) "clojure.core")
+ (namespaces-on-classpath :prefix "clojure.core"))))
+ (testing "directory"
+ (is (=
+ #{'bultitude.core 'bultitude.core-test}
+ (set (namespaces-on-classpath :prefix "bultitude"))))))

0 comments on commit 73bdcba

Please sign in to comment.
Something went wrong with that request. Please try again.