From 2e201cd7d8a89b7d26831fd78d9758fc5f1612d2 Mon Sep 17 00:00:00 2001 From: Ilya Pimenov Date: Fri, 15 Nov 2013 15:59:36 +0100 Subject: [PATCH 1/2] Transitive dependency support --- project.clj | 2 +- src/leiningen/sub.clj | 46 +++++++++++++++---- subtest/child/project.clj | 7 ++- subtest/child2/project.clj | 7 ++- subtest/child3/.gitignore | 10 ++++ subtest/child3/README.md | 13 ++++++ subtest/child3/project.clj | 9 ++++ subtest/child3/src/child2/core.clj | 6 +++ subtest/child3/test/child2/core_test.clj | 7 +++ subtest/common-child/.gitignore | 10 ++++ subtest/common-child/README.md | 13 ++++++ subtest/common-child/project.clj | 8 ++++ subtest/common-child/src/child2/core.clj | 6 +++ .../common-child/test/child2/core_test.clj | 7 +++ subtest/project.clj | 4 +- 15 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 subtest/child3/.gitignore create mode 100644 subtest/child3/README.md create mode 100644 subtest/child3/project.clj create mode 100644 subtest/child3/src/child2/core.clj create mode 100644 subtest/child3/test/child2/core_test.clj create mode 100644 subtest/common-child/.gitignore create mode 100644 subtest/common-child/README.md create mode 100644 subtest/common-child/project.clj create mode 100644 subtest/common-child/src/child2/core.clj create mode 100644 subtest/common-child/test/child2/core_test.clj diff --git a/project.clj b/project.clj index c6ef0f7..8b72b2a 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject lein-sub "0.3.0" +(defproject lein-sub "0.3.1" :description "Leiningen Subprojects plugin" :url "https://github.com/kumarshantanu/lein-sub" :license {:name "Eclipse Public License" diff --git a/src/leiningen/sub.clj b/src/leiningen/sub.clj index 68537e0..b68e5db 100644 --- a/src/leiningen/sub.clj +++ b/src/leiningen/sub.clj @@ -3,15 +3,47 @@ [leiningen.core.main :as main] [leiningen.core.project :as project])) +(defn proj-version [proj] + [(symbol (:group proj) (:name proj)) (:version proj)]) (defn apply-task-to-subproject - [sub-proj-dir task-name args] - (println "Reading project from" sub-proj-dir) - (let [sub-project (project/init-project - (project/read (str sub-proj-dir "/project.clj"))) - new-task-name (main/lookup-alias task-name sub-project)] + [sub-project task-name args] + (println "Building project " (proj-version sub-project)) + (let [new-task-name (main/lookup-alias task-name sub-project)] (main/apply-task new-task-name sub-project args))) +(defn read-all-subprojects + [sub-proj-dirs] + (map #(project/init-project (project/read (str % "/project.clj"))) sub-proj-dirs)) + +(defn perform-in-order [enriched-projects task-name args] + "Applies tasks to all projects in a recursion, unless finished or a cycle was encountered" + (let [ build-this-round (filter #(empty? (:internal-deps %)) enriched-projects) + built-this-round (into #{} (map #(proj-version %) build-this-round)) + build-next-round (filter #(not (empty? (:internal-deps %))) enriched-projects) + build-next-round (map #(assoc % + :internal-deps + (filter + (fn [dep](not (contains? built-this-round dep))) + (:internal-deps %))) build-next-round)] + (if (and (empty? build-this-round) (not (empty? build-next-round))) + (main/abort (str "Cycle dependecy, cannot resolve proper build order for projects: " + (into #{} (map #(proj-version %) build-next-round)))) + (if (not (empty? build-this-round)) + (do + (doseq [each build-this-round] + (apply-task-to-subproject each task-name args)) + (perform-in-order build-next-round task-name args)))))) + + +(defn enriched-projects [subprojects] + "Adds :internal-deps vector with all dependencies that are within this build-tree" + (let [all-subprojects (into #{} (map #(proj-version %) subprojects)) + enriched-projects + (map (fn [project](assoc project + :internal-deps + (into [] (filterv #(contains? all-subprojects %) (:dependencies project))))) subprojects)] + enriched-projects)) (defn resolve-subprojects "Parse `args` and return [sub-projects task-name args]" @@ -42,10 +74,8 @@ or specify subproject dirs via command line: Note: Each sub-project directory should have its own project.clj file"))) - (defn sub "Run task for all subprojects" [project task-name & args] (let [[subprojects task-name args] (resolve-subprojects project task-name args)] - (doseq [each subprojects] - (apply-task-to-subproject each task-name args)))) + (perform-in-order (enriched-projects (read-all-subprojects subprojects)) task-name args))) diff --git a/subtest/child/project.clj b/subtest/child/project.clj index e8f560b..b059398 100644 --- a/subtest/child/project.clj +++ b/subtest/child/project.clj @@ -1,6 +1,9 @@ -(defproject child "0.1.0-SNAPSHOT" +(def version (clojure.string/trim (:out (clojure.java.shell/sh "git" "describe" "--always")))) + +(defproject subtest/child version :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.4.0"]]) + :dependencies [[org.clojure/clojure "1.4.0"] + [subtest/common-child ~version]]) diff --git a/subtest/child2/project.clj b/subtest/child2/project.clj index 6f4961e..8cbe05d 100644 --- a/subtest/child2/project.clj +++ b/subtest/child2/project.clj @@ -1,6 +1,9 @@ -(defproject child2 "0.1.0-SNAPSHOT" +(def version (clojure.string/trim (:out (clojure.java.shell/sh "git" "describe" "--always")))) + +(defproject subtest/child2 version :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.4.0"]]) + :dependencies [[org.clojure/clojure "1.4.0"] + [subtest/common-child ~version]]) diff --git a/subtest/child3/.gitignore b/subtest/child3/.gitignore new file mode 100644 index 0000000..ee508f7 --- /dev/null +++ b/subtest/child3/.gitignore @@ -0,0 +1,10 @@ +/target +/lib +/classes +/checkouts +pom.xml +*.jar +*.class +.lein-deps-sum +.lein-failures +.lein-plugins diff --git a/subtest/child3/README.md b/subtest/child3/README.md new file mode 100644 index 0000000..05575a9 --- /dev/null +++ b/subtest/child3/README.md @@ -0,0 +1,13 @@ +# child2 + +A Clojure library designed to ... well, that part is up to you. + +## Usage + +FIXME + +## License + +Copyright © 2012 FIXME + +Distributed under the Eclipse Public License, the same as Clojure. diff --git a/subtest/child3/project.clj b/subtest/child3/project.clj new file mode 100644 index 0000000..86bfee4 --- /dev/null +++ b/subtest/child3/project.clj @@ -0,0 +1,9 @@ +(def version (clojure.string/trim (:out (clojure.java.shell/sh "git" "describe" "--always")))) + +(defproject subtest/child3 version + :description "FIXME: write description" + :url "http://example.com/FIXME" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + :dependencies [[org.clojure/clojure "1.4.0"] + [subtest/child2 ~version]]) diff --git a/subtest/child3/src/child2/core.clj b/subtest/child3/src/child2/core.clj new file mode 100644 index 0000000..54670a2 --- /dev/null +++ b/subtest/child3/src/child2/core.clj @@ -0,0 +1,6 @@ +(ns child2.core) + +(defn foo + "I don't do a whole lot." + [x] + (println x "Hello, World!")) diff --git a/subtest/child3/test/child2/core_test.clj b/subtest/child3/test/child2/core_test.clj new file mode 100644 index 0000000..fff2008 --- /dev/null +++ b/subtest/child3/test/child2/core_test.clj @@ -0,0 +1,7 @@ +(ns child2.core-test + (:use clojure.test + child2.core)) + +(deftest a-test + (testing "FIXME, I fail." + (is (= 0 1)))) \ No newline at end of file diff --git a/subtest/common-child/.gitignore b/subtest/common-child/.gitignore new file mode 100644 index 0000000..ee508f7 --- /dev/null +++ b/subtest/common-child/.gitignore @@ -0,0 +1,10 @@ +/target +/lib +/classes +/checkouts +pom.xml +*.jar +*.class +.lein-deps-sum +.lein-failures +.lein-plugins diff --git a/subtest/common-child/README.md b/subtest/common-child/README.md new file mode 100644 index 0000000..05575a9 --- /dev/null +++ b/subtest/common-child/README.md @@ -0,0 +1,13 @@ +# child2 + +A Clojure library designed to ... well, that part is up to you. + +## Usage + +FIXME + +## License + +Copyright © 2012 FIXME + +Distributed under the Eclipse Public License, the same as Clojure. diff --git a/subtest/common-child/project.clj b/subtest/common-child/project.clj new file mode 100644 index 0000000..819ce10 --- /dev/null +++ b/subtest/common-child/project.clj @@ -0,0 +1,8 @@ +(def version (clojure.string/trim (:out (clojure.java.shell/sh "git" "describe" "--always")))) + +(defproject subtest/common-child version + :description "FIXME: write description" + :url "http://example.com/FIXME" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + :dependencies [[org.clojure/clojure "1.4.0"]]) diff --git a/subtest/common-child/src/child2/core.clj b/subtest/common-child/src/child2/core.clj new file mode 100644 index 0000000..54670a2 --- /dev/null +++ b/subtest/common-child/src/child2/core.clj @@ -0,0 +1,6 @@ +(ns child2.core) + +(defn foo + "I don't do a whole lot." + [x] + (println x "Hello, World!")) diff --git a/subtest/common-child/test/child2/core_test.clj b/subtest/common-child/test/child2/core_test.clj new file mode 100644 index 0000000..fff2008 --- /dev/null +++ b/subtest/common-child/test/child2/core_test.clj @@ -0,0 +1,7 @@ +(ns child2.core-test + (:use clojure.test + child2.core)) + +(deftest a-test + (testing "FIXME, I fail." + (is (= 0 1)))) \ No newline at end of file diff --git a/subtest/project.clj b/subtest/project.clj index bd3f59d..2f250ca 100644 --- a/subtest/project.clj +++ b/subtest/project.clj @@ -4,5 +4,5 @@ :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.4.0"]] - :plugins [[lein-sub "0.3.0"]] - :sub ["child" "child2"]) + :plugins [[lein-sub "0.3.1"]] + :sub ["common-child" "child" "child2" "child3"]) From 0158fca572f6ce370e6614e1f0149dc1e9a2c172 Mon Sep 17 00:00:00 2001 From: Ilya Pimenov Date: Mon, 18 Nov 2013 13:53:23 +0100 Subject: [PATCH 2/2] Added -d property to switch between user-specified and dependency discovery option --- README.md | 6 ++++++ src/leiningen/sub.clj | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index da46358..b2ea461 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,12 @@ You can pass subproject directory locations via command line (overrides `:sub`): $ lein sub -s "module/foo-common:module/dep-vendor-xyz" jar ``` +You can force dependency discovery between sub-projects (overrides build order specified in the `:sub` vector): + +```bash +$ lein sub clean -d +``` + ## Getting in touch diff --git a/src/leiningen/sub.clj b/src/leiningen/sub.clj index b68e5db..b126135 100644 --- a/src/leiningen/sub.clj +++ b/src/leiningen/sub.clj @@ -12,6 +12,11 @@ (let [new-task-name (main/lookup-alias task-name sub-project)] (main/apply-task new-task-name sub-project args))) +(defn apply-task-to-subproject-dir + [sub-project-dir task-name args] + (let [ sub-project (project/init-project (project/read (str sub-project-dir "/project.clj")))] + (apply-task-to-subproject sub-project task-name args))) + (defn read-all-subprojects [sub-proj-dirs] (map #(project/init-project (project/read (str % "/project.clj"))) sub-proj-dirs)) @@ -78,4 +83,11 @@ Note: Each sub-project directory should have its own project.clj file"))) "Run task for all subprojects" [project task-name & args] (let [[subprojects task-name args] (resolve-subprojects project task-name args)] - (perform-in-order (enriched-projects (read-all-subprojects subprojects)) task-name args))) + (cond + ;; -d would trigger "discovery mode" build order + (= "-d" (first args)) + (perform-in-order (enriched-projects (read-all-subprojects subprojects)) task-name (rest args)) + ;; the normal way will follow artifacts order in the build script + :else + (doseq [each subprojects] + (apply-task-to-subproject-dir each task-name args)))))