Permalink
Browse files

add functionality for v0.2

  • Loading branch information...
1 parent ef7e3c7 commit 2bcba98556d4ebebe7bfeb642bb6b75a8a0b2798 @kumarshantanu committed Jul 13, 2011
Showing with 204 additions and 54 deletions.
  1. +7 −8 README.md
  2. +1 −1 project.clj
  3. +93 −45 src/leiningen/localrepo.clj
  4. +103 −0 src/leiningen/localrepo/internal.clj
View
@@ -7,11 +7,11 @@ Leiningen plugin to work with local Maven repository.
Either install as a plugin:
- $ lein plugin install lein-localrepo "0.1.1"
+ $ lein plugin install lein-localrepo "0.2"
Or, include as a dev-dependency:
- :dev-dependencies [lein-localrepo "0.1.1"]
+ :dev-dependencies [lein-localrepo "0.2"]
### Guess Leiningen (Maven) coordinates of a file
@@ -38,16 +38,15 @@ Examples:
$ lein localrepo coords /tmp/foobar-1.0.0-SNAPSHOT.jar | xargs lein localrepo install
-### List artifacts in local Maven repository (Not Yet Implemented):
+### List artifacts in local Maven repository ('-d' Not Yet Implemented):
- $ lein localrepo list [<[groupId/]artifactId> [<version>]]
+ $ lein localrepo list [-f | -d]
Examples:
- $ lein localrepo list # lists all artifacts, all versions
- $ lein localrepo list com.example/foo # lists all versions
- $ lein localrepo list foomatic # lists all versions
- $ lein localrepo list com.example/foo 1.3 # lists only specified version
+ $ lein localrepo list # lists all artifacts, all versions
+ $ lein localrepo list -f # lists all artifacts and filenames
+ $ lein localrepo list -d # lists all artifacts in detail
### Remove artifacts from local Maven repository (Not Yet Implemented):
View
@@ -1,3 +1,3 @@
-(defproject lein-localrepo "0.1.1"
+(defproject lein-localrepo "0.2"
:description "Leiningen local repository plugin"
:dev-dependencies [[org.clojure/clojure "1.2.1"]])
@@ -2,22 +2,17 @@
(:require
[leiningen.util.maven :as mvn]
[leiningen.install :as ins]
- [leiningen.pom :as pom]
+ [leiningen.pom :as pom]
[clojure.java.io :as jio]
- [clojure.string :as str])
+ [clojure.string :as str]
+ [clojure.pprint :as ppr]
+ [leiningen.localrepo.internal :as in])
(:import
(java.io File)
(java.util.jar JarFile)
(org.apache.maven.artifact.installer ArtifactInstaller)))
-(defn illegal-arg
- "Throw IllegalArgumentException using the args"
- [arg & more]
- (let [msg (apply str (interpose " " (into [arg] more)))]
- (throw (IllegalArgumentException. msg))))
-
-
(defn split-artifactid
"Given 'groupIp/artifactId' string split them up and return
as a vector of 2 elements."
@@ -28,49 +23,22 @@
(if (or (zero? tcount)
(> tcount 2)
(nil? gi))
- (illegal-arg "Invalid groupId/artifactId:" artifact-id)
+ (in/illegal-arg "Invalid groupId/artifactId:" artifact-id)
(if (nil? ai)
[gi gi]
[gi ai]))))
-(defn ^String java-filepath
- "Accept path (of a file) as argument and return a uniform file path for all
- operating systems.
- Example: \"C:\\path\\to\\file.txt\" becomes \"C:/path/to/file.txt\"
- See also: split-filepath"
- [s]
- (let [p (if (instance? File s) (.getAbsolutePath ^File s)
- (str s))]
- (.replace ^String p "\\" "/")))
-
-
-(defn ^String split-filepath
- "Given a complete path, split into filedir and filename and return as vector.
- The filedir is normalized as uniform Java filepath.
- See also: java-filepath"
- [s]
- (let [jf (java-filepath s)
- sf (str/split jf #"/")]
- [(str/join "/" (drop-last sf)) (last sf)]))
-
-
-(defn ^String pick-filename
- "Given a filepath, return the filename portion from it."
- [s]
- (last (split-filepath s)))
-
-
(defn c-coords
"Guess Leiningen coordinates of given filename.
Example:
Input - local/jars/foo-bar-1.0.6.jar
Output - foo-bar-1.0.6.jar foo-bar 1.0.6"
[^String filepath]
- (let [filename (pick-filename filepath)
- tokens (drop-last
- (re-find (re-matcher #"(.+)\-(\d.+)\.(\w+)"
- filename)))
+ (let [filename (in/pick-filename filepath)
+ tokens (drop-last
+ (re-find (re-matcher #"(.+)\-(\d.+)\.(\w+)"
+ filename)))
[_ artifact-id version] tokens]
(println filepath (str artifact-id "/" artifact-id) version)))
@@ -98,10 +66,85 @@
(.install installer the-file artifact local-repo)))
+(defn read-artifact-entries
+ "Read artifact entries from specified `dir` and return as a list. If
+ dir contains only sub-dirs then it recurses to find actual entries."
+ [dir]
+ (assert (in/dir? dir))
+ (let [entries (filter #(not (.startsWith (.getName %) "."))
+ (.listFiles dir))
+ {subdirs :dir
+ nondirs :file} (group-by in/dir-or-file entries)]
+ (if (not (empty? subdirs))
+ (reduce into [] (map read-artifact-entries subdirs))
+ (let [ignore-ext #{"lastUpdated" "pom" "properties"
+ "repositories" "sha1" "xml"}
+ arti-file? #(in/not-contains? ignore-ext
+ (in/pick-filename-ext %))]
+ (for [each (filter #(arti-file? (.getName %)) nondirs)]
+ ;; parent = version, parent->parent = artifactId
+ ;; parent->parent->parent[relative-path] = groupId
+ (let [parent (.getParentFile each)
+ version (.getName parent)
+ artifact-id (.getName (.getParentFile parent))
+ group-path (in/java-filepath
+ (in/relative-path mvn/local-repo-path
+ (-> parent
+ .getParentFile
+ .getParentFile
+ .getAbsolutePath)))
+ group-clean (let [slash? #(= \/ %)
+ rtrim #(if (slash? (last %)) (drop-last %) %)
+ ltrim #(if (slash? (first %)) (rest %) %)]
+ (apply str (-> group-path rtrim ltrim)))
+ group-id (str/replace group-clean "/" ".")]
+ [group-id
+ artifact-id
+ version
+ (.getName each)]))))))
+
+
(defn c-list
"List artifacts in local Maven repo"
[& args]
- (println "Not yet implemented"))
+ (if (and (not (zero? (count args)))
+ (or (> (count args) 1)
+ (not (contains? #{"-f"} (first args)))))
+ (println "Invalid argument(s):" (apply str (interpose " " args))
+ " ==> Allowed: [-f]")
+ (let [artifact-entries (read-artifact-entries
+ (jio/file mvn/local-repo-path))
+ by-group-id (group-by first artifact-entries)]
+ (doseq [group-id (keys by-group-id)]
+ ;; print group-id header
+ (println (format "[%s]" group-id))
+ (let [by-artifact-id (group-by second
+ (get by-group-id group-id))]
+ (doseq [artifact-id (keys by-artifact-id)]
+ (let [versions (distinct
+ (map #(nth % 2)
+ (get by-artifact-id artifact-id)))]
+ (case (or (first args) :nil)
+ :nil (println
+ (format " %s (%s)" artifact-id
+ (apply str (interpose ", "
+ versions))))
+ "-f" (do (println (format " %s" artifact-id))
+ (doseq [each-v versions]
+ (println (format " [%s]" each-v))
+ (let [artifacts (get by-artifact-id
+ artifact-id)]
+ (doseq [each-a (filter #(= each-v
+ (nth % 2))
+ artifacts)]
+ (println
+ (format " %s"
+ (last each-a)))))))
+ "-d" (println
+ "Detail option is not yet implemented")
+ (println
+ (str "Bad arg(s): "
+ (apply str (interpose " " args))))))))))))
(defn c-remove
@@ -118,9 +161,13 @@ Leiningen plugin to work with local Maven repository.
coords Guess Leiningen (Maven) coords of a file
install Install artifact to local repository
-list List artifacts in local repository (Not Yet Implemented)
+list List artifacts in local repository
remove Remove artifact from local repository (Not Yet Implemented)
help This help screen
+
+For help on individual commands use 'help' with command name, e.g.:
+
+$ lein localrepo help install
"))
([command]
(case command
@@ -129,7 +176,7 @@ help This help screen
"list" (doc c-list)
"remove" (doc c-remove)
"help" (doc c-help)
- (illegal-arg "Illegal command:" command
+ (in/illegal-arg "Illegal command:" command
", Allowed: coords, install, list, remove, help"))))
@@ -148,7 +195,8 @@ help This help screen
(case command
"coords" (apply-cmd #(= argc 1) command c-coords args)
"install" (apply-cmd #(= argc 3) command c-install args)
- "list" (apply-cmd #(>= argc 0) command c-list args)
+ "list" (apply-cmd #(or (= argc 0)
+ (= argc 1)) command c-list args)
"remove" (apply-cmd #(>= argc 0) command c-remove args)
"help" (apply-cmd #(or (= argc 0)
(= argc 1)) command c-help args)
@@ -0,0 +1,103 @@
+(ns leiningen.localrepo.internal
+ "Utility functions - mostly taken/adapted from Clj-MiscUtil:
+ https://bitbucket.org/kumarshantanu/clj-miscutil/src"
+ (:require [clojure.string :as str])
+ (:import (java.io File)))
+
+
+(defn illegal-arg
+ "Throw IllegalArgumentException using the args"
+ [arg & more]
+ (let [msg (apply str (interpose " " (into [arg] more)))]
+ (throw (IllegalArgumentException. msg))))
+
+
+(defn ^String java-filepath
+ "Accept path (of a file) as argument and return a uniform file path for all
+ operating systems.
+ Example: \"C:\\path\\to\\file.txt\" becomes \"C:/path/to/file.txt\"
+ See also: split-filepath"
+ [s]
+ (let [p (if (instance? File s) (.getAbsolutePath ^File s)
+ (str s))]
+ (.replace ^String p "\\" "/")))
+
+
+(defn ^String split-filepath
+ "Given a complete path, split into filedir and filename and return as vector.
+ The filedir is normalized as uniform Java filepath.
+ See also: java-filepath"
+ [s]
+ (let [jf (java-filepath s)
+ sf (str/split jf #"/")]
+ [(str/join "/" (drop-last sf)) (last sf)]))
+
+
+(defn ^String pick-filename
+ "Given a filepath, return the filename portion from it."
+ [s]
+ (last (split-filepath s)))
+
+
+(defn split-filename
+ "Given a partial or complete file path, split into filename and extension and
+ return as vector."
+ [s]
+ (let [f (pick-filename s)
+ sfe (str/split f #"\.")
+ sfc (count sfe)
+ sf1 (first sfe)
+ sf2 (second sfe)]
+ (cond
+ (= 1 sfc) (conj sfe "")
+ (and (= 2 sfc) (empty? sf1)) [(str "." sf2) ""]
+ :else [(str/join "." (drop-last sfe)) (last sfe)])))
+
+
+(defn ^String pick-filename-name
+ "Given a filepath, return the filename (without extension) portion from it."
+ [s]
+ (first (split-filename s)))
+
+
+(defn ^String pick-filename-ext
+ "Given a filepath, return the file extension portion from it."
+ [s]
+ (last (split-filename s)))
+
+
+(defn relative-path
+ "Given base path and an absolute path, finds the relative path."
+ [^String base ^String path]
+ ;; new File(base).toURI()
+ ;; .relativize(new
+ ;; File(path).toURI()).getPath();
+ (let [base-uri (-> base
+ File.
+ .toURI)
+ path-uri (-> path
+ File.
+ .toURI)]
+ (-> base-uri
+ (.relativize path-uri)
+ .getPath)))
+
+
+(defn dir?
+ "Return true if `d` is a directory, false otherwise."
+ [d]
+ (and (instance? File d)
+ (.isDirectory d)))
+
+
+(defn dir-or-file
+ "Return :dir if `f` (java.io.File) is a directory, :file otherwise."
+ [f]
+ (assert (instance? File f))
+ (if (dir? f) :dir :file))
+
+
+(defn not-contains?
+ "Same as (not (contains? haystack needle))"
+ [haystack needle]
+ (not (contains? haystack needle)))

0 comments on commit 2bcba98

Please sign in to comment.