WIP: merge change task and release.
This commit is contained in:
parent
80d4f130fc
commit
c83b2facfe
4 changed files with 69 additions and 81 deletions
|
@ -181,17 +181,17 @@
|
||||||
:clean-targets ^:top-displace [:target-path]
|
:clean-targets ^:top-displace [:target-path]
|
||||||
;; TODO: remove :top-displace for :prep-tasks in 3.0
|
;; TODO: remove :top-displace for :prep-tasks in 3.0
|
||||||
:prep-tasks ^:top-displace ["javac" "compile"]
|
:prep-tasks ^:top-displace ["javac" "compile"]
|
||||||
:prep-tasks ^:top-displace [["vcs" "assert-committed"]
|
:release-tasks ^:top-displace [["vcs" "assert-committed"]
|
||||||
["change" "version"
|
["change" "version"
|
||||||
"leiningen.release/bump-version" "release"]
|
"leiningen.release/bump-version" "release"]
|
||||||
["vcs" "commit"]
|
["vcs" "commit"]
|
||||||
["vcs" "tag"]
|
["vcs" "tag"]
|
||||||
["deploy"]
|
["deploy"]
|
||||||
["change" "version"
|
["change" "version"
|
||||||
;; TODO: level here should come from task arg
|
;; TODO: level here should come from task arg
|
||||||
"leiningen.release/bump-version" "minor"]
|
"leiningen.release/bump-version" "minor"]
|
||||||
["vcs" "commit"]
|
["vcs" "commit"]
|
||||||
["vcs" "push"]]
|
["vcs" "push"]]
|
||||||
:jar-exclusions [#"^\."]
|
:jar-exclusions [#"^\."]
|
||||||
:certificates ["clojars.pem"]
|
:certificates ["clojars.pem"]
|
||||||
:offline? (not (nil? (System/getenv "LEIN_OFFLINE")))
|
:offline? (not (nil? (System/getenv "LEIN_OFFLINE")))
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
(ns leiningen.change
|
(ns leiningen.change
|
||||||
|
"Rewrite project.clj by applying a function."
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[clojure.zip :as zip]
|
[clojure.zip :as zip]
|
||||||
[net.cgrand.sjacket :refer [str-pt]]
|
[clojure.java.io :as io]
|
||||||
[net.cgrand.sjacket.parser :refer [parser]]))
|
[net.cgrand.sjacket :as sj]
|
||||||
|
[net.cgrand.sjacket.parser :as parser]))
|
||||||
|
|
||||||
;;; Helpers
|
;;; Helpers
|
||||||
|
|
||||||
|
@ -12,39 +14,22 @@
|
||||||
(defn- clj->sjacket [value]
|
(defn- clj->sjacket [value]
|
||||||
(if (string? value)
|
(if (string? value)
|
||||||
(str "\"" value "\"")
|
(str "\"" value "\"")
|
||||||
(-> value print-str parser :content first)))
|
(-> value print-str parser/parser :content first)))
|
||||||
|
|
||||||
;; NOTE: this destroy comments, formatting, etc.
|
;; NOTE: this destroy comments, formatting, etc.
|
||||||
;; NOTE: read-string may throw parse errors on badly formed config..
|
|
||||||
;; is this an issue or will files already have been sanity
|
|
||||||
;; checked before this task can run?
|
|
||||||
(defn- sjacket->clj [value]
|
(defn- sjacket->clj [value]
|
||||||
(->> value str-pt read-string))
|
(->> value sj/str-pt read-string))
|
||||||
|
|
||||||
(defn- lookup-var [x]
|
(defn ^:internal normalize-path [value]
|
||||||
;; ensure it's a namespaced var reference to avoid error
|
(if (coll? value)
|
||||||
(if (re-find #"^[a-zA-Z]+\..+\/.+$" x)
|
value
|
||||||
(-> x symbol find-var var-get)))
|
(map keyword (remove empty? (str/split value #":")))))
|
||||||
|
|
||||||
(defn ^:internal normalize-path
|
(defn ^:internal collapse-fn [f args]
|
||||||
"Coerce scalars, colls and cli-encoded lists of symbols/strings into keyword vector"
|
(let [f (if (ifn? f)
|
||||||
[value]
|
f
|
||||||
(mapv keyword
|
(resolve (symbol f)))]
|
||||||
(if (coll? value)
|
#(apply f % args)))
|
||||||
(map name value)
|
|
||||||
(let [value (name value)]
|
|
||||||
(if (re-find #":" (name value))
|
|
||||||
(remove empty? (str/split (name value) #":"))
|
|
||||||
[(name value)])))))
|
|
||||||
|
|
||||||
(defn ^:internal collapse-fn
|
|
||||||
"Partially apply args to right if fn, else return constant of first arg.
|
|
||||||
If string corresponds to a namespaced var, substite value for string"
|
|
||||||
[fn args]
|
|
||||||
(let [fn' (or (and (string? fn) (lookup-var fn)) fn)]
|
|
||||||
(if (fn? fn')
|
|
||||||
#(apply fn' % args)
|
|
||||||
(constantly fn'))))
|
|
||||||
|
|
||||||
;;; Traversal
|
;;; Traversal
|
||||||
|
|
||||||
|
@ -84,8 +69,8 @@
|
||||||
(remove (comp #{:whitespace :comment} :tag zip/node))
|
(remove (comp #{:whitespace :comment} :tag zip/node))
|
||||||
first))
|
first))
|
||||||
|
|
||||||
(defn- get-project [project-str]
|
(defn- parse-project [project-str]
|
||||||
(-> (parser project-str)
|
(-> (parser/parser project-str)
|
||||||
zip/xml-zip
|
zip/xml-zip
|
||||||
find-defproject
|
find-defproject
|
||||||
(or (fail-argument! "Project definition not found"))
|
(or (fail-argument! "Project definition not found"))
|
||||||
|
@ -123,20 +108,23 @@
|
||||||
|
|
||||||
;;; Public API
|
;;; Public API
|
||||||
|
|
||||||
(defn change*
|
(defn change-string
|
||||||
[project-str key-or-path fn & args]
|
[project-str key-or-path f & args]
|
||||||
(let [fn' (collapse-fn fn args)
|
(let [f (collapse-fn f args)
|
||||||
fn'' (comp clj->sjacket fn' sjacket->clj)
|
wrapped-f (comp clj->sjacket f sjacket->clj)
|
||||||
path (normalize-path key-or-path)
|
path (normalize-path key-or-path)
|
||||||
proj (get-project project-str)]
|
proj (parse-project project-str)]
|
||||||
(str-pt
|
(sj/str-pt
|
||||||
|
;; TODO: support :artifact-id, :group-id
|
||||||
(if (= path [:version])
|
(if (= path [:version])
|
||||||
(update-version proj fn'')
|
(update-version proj wrapped-f)
|
||||||
(update-setting proj path fn'')))))
|
(update-setting proj path wrapped-f)))))
|
||||||
|
|
||||||
(defn change
|
(defn change
|
||||||
"Rewrite project.clj with new settings"
|
"Rewrite project.clj with f applied to the value at key-or-path.
|
||||||
[project & args]
|
|
||||||
;; cannot work with project, want to preserve formatting, comments, etc
|
TODO: document accepted args."
|
||||||
(let [source (slurp "project.clj")]
|
[project key-or-path f & args]
|
||||||
(spit "project.clj" (apply change* source args))))
|
;; cannot work with project map, want to preserve formatting, comments, etc
|
||||||
|
(let [source (slurp (io/file (:root project) "project.clj"))]
|
||||||
|
(spit "project.clj" (apply change-string source key-or-path f args))))
|
||||||
|
|
|
@ -13,23 +13,23 @@
|
||||||
(testing "project definition not found"
|
(testing "project definition not found"
|
||||||
(is (thrown-with-msg?
|
(is (thrown-with-msg?
|
||||||
IllegalArgumentException #"Project definition not found"
|
IllegalArgumentException #"Project definition not found"
|
||||||
(change* ";;(defproject stealth.library \"0.0.0\")"
|
(change-string ";;(defproject stealth.library \"0.0.0\")"
|
||||||
:version "0.0.1"))))
|
:version "0.0.1"))))
|
||||||
|
|
||||||
(testing "project version not found"
|
(testing "project version not found"
|
||||||
(is (thrown-with-msg?
|
(is (thrown-with-msg?
|
||||||
IllegalArgumentException #"Project version not found"
|
IllegalArgumentException #"Project version not found"
|
||||||
(change* "(defproject com.someproject :dependencies [[\"some.thing\" \"2.3.1\"]])"
|
(change-string "(defproject com.someproject :dependencies [[\"some.thing\" \"2.3.1\"]])"
|
||||||
:version "1.2.3"))))
|
:version "1.2.3"))))
|
||||||
|
|
||||||
(testing "simplest possible case"
|
(testing "simplest possible case"
|
||||||
(is (= "(defproject leingingen.change \"0.0.2-SNAPSHOT\")"
|
(is (= "(defproject leingingen.change \"0.0.2-SNAPSHOT\")"
|
||||||
(change* "(defproject leingingen.change \"0.0.1\")"
|
(change-string "(defproject leingingen.change \"0.0.1\")"
|
||||||
:version "0.0.2-SNAPSHOT"))))
|
:version "0.0.2-SNAPSHOT"))))
|
||||||
|
|
||||||
(testing "the largest project.clj in the repo"
|
(testing "the largest project.clj in the repo"
|
||||||
(let [before (slurp (clojure.java.io/resource "leiningen/help/project.clj"))
|
(let [before (slurp (clojure.java.io/resource "leiningen/help/project.clj"))
|
||||||
after (change* before :version "6.4.1")]
|
after (change-string before :version "6.4.1")]
|
||||||
;; check the key portion
|
;; check the key portion
|
||||||
(is (= "(defproject org.example/sample \"6.4.1\" " (.substring after 529 568)))
|
(is (= "(defproject org.example/sample \"6.4.1\" " (.substring after 529 568)))
|
||||||
;; check a random dependency for changes
|
;; check a random dependency for changes
|
||||||
|
@ -38,42 +38,42 @@
|
||||||
(deftest test-external-function
|
(deftest test-external-function
|
||||||
(testing "regular function by function reference"
|
(testing "regular function by function reference"
|
||||||
(is (= "(defproject leingingen.change \"1.9.53-SNAPSHOT\")"
|
(is (= "(defproject leingingen.change \"1.9.53-SNAPSHOT\")"
|
||||||
(change* "(defproject leingingen.change \"1.9.52-SNAPSHOT\")"
|
(change-string "(defproject leingingen.change \"1.9.52-SNAPSHOT\")"
|
||||||
:version bump-version))))
|
:version bump-version))))
|
||||||
|
|
||||||
(testing "regular function by function reference"
|
(testing "regular function by function reference"
|
||||||
(is (= "(defproject leingingen.change \"1.9.53-SNAPSHOT\")"
|
(is (= "(defproject leingingen.change \"1.9.53-SNAPSHOT\")"
|
||||||
(change* "(defproject leingingen.change \"1.9.52-SNAPSHOT\")"
|
(change-string "(defproject leingingen.change \"1.9.52-SNAPSHOT\")"
|
||||||
:version "leiningen.test.change/bump-version")))))
|
:version "leiningen.test.change/bump-version")))))
|
||||||
|
|
||||||
(deftest test-set-regular-key
|
(deftest test-set-regular-key
|
||||||
|
|
||||||
(testing "can set a key"
|
(testing "can set a key"
|
||||||
(is (= "(defproject leingingen.change \"0.0.1\" :description \"a dynamic description\")"
|
(is (= "(defproject leingingen.change \"0.0.1\" :description \"a dynamic description\")"
|
||||||
(change* "(defproject leingingen.change \"0.0.1\" :description \"a static description\")"
|
(change-string "(defproject leingingen.change \"0.0.1\" :description \"a static description\")"
|
||||||
:description "a dynamic description"))))
|
:description "a dynamic description"))))
|
||||||
|
|
||||||
(testing "can create a new key"
|
(testing "can create a new key"
|
||||||
(is (= "(defproject leingingen.change \"0.0.1\" :description \"a dynamic description\")"
|
(is (= "(defproject leingingen.change \"0.0.1\" :description \"a dynamic description\")"
|
||||||
(change* "(defproject leingingen.change \"0.0.1\")"
|
(change-string "(defproject leingingen.change \"0.0.1\")"
|
||||||
:description "a dynamic description")))))
|
:description "a dynamic description")))))
|
||||||
|
|
||||||
(deftest test-nested-key
|
(deftest test-nested-key
|
||||||
|
|
||||||
(testing "can set a nested key"
|
(testing "can set a nested key"
|
||||||
(is (= "(defproject leingingen.change \"0.0.1\" :license {:url \"http://example.com\"})"
|
(is (= "(defproject leingingen.change \"0.0.1\" :license {:url \"http://example.com\"})"
|
||||||
(change* "(defproject leingingen.change \"0.0.1\" :license {:url \"http://old.com\"})"
|
(change-string "(defproject leingingen.change \"0.0.1\" :license {:url \"http://old.com\"})"
|
||||||
[:license :url] "http://example.com"))))
|
[:license :url] "http://example.com"))))
|
||||||
|
|
||||||
(testing "can create a nested value"
|
(testing "can create a nested value"
|
||||||
(is (= "(defproject leingingen.change \"0.0.1\" :a {:b {:c 1}})"
|
(is (= "(defproject leingingen.change \"0.0.1\" :a {:b {:c 1}})"
|
||||||
(change* "(defproject leingingen.change \"0.0.1\")"
|
(change-string "(defproject leingingen.change \"0.0.1\")"
|
||||||
[:a :b :c] 1))))
|
[:a :b :c] 1))))
|
||||||
|
|
||||||
(testing "can understand cli short form"
|
(testing "can understand cli short form"
|
||||||
(is (= "(defproject leingingen.change \"0.0.1\" :license {:url \"http://example.com\"})"
|
(is (= "(defproject leingingen.change \"0.0.1\" :license {:url \"http://example.com\"})"
|
||||||
(change* "(defproject leingingen.change \"0.0.1\")"
|
(change-string "(defproject leingingen.change \"0.0.1\")"
|
||||||
:license:url "http://example.com")))))
|
:license:url "http://example.com")))))
|
||||||
|
|
||||||
(deftest test-normalize-path
|
(deftest test-normalize-path
|
||||||
(is (= [:a]
|
(is (= [:a]
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
(is (= (nth semver-test-data 2)
|
(is (= (nth semver-test-data 2)
|
||||||
(version-map->string (second semver-test-data))))))
|
(version-map->string (second semver-test-data))))))
|
||||||
|
|
||||||
(deftest test-increment-version
|
(deftest test-bump-version
|
||||||
(testing "Testing semantic version increment"
|
(testing "Testing semantic version increment"
|
||||||
(doseq [semver-test-data valid-semver-version-values]
|
(doseq [semver-test-data valid-semver-version-values]
|
||||||
(testing (format "with valid version: %s\n"
|
(testing (format "with valid version: %s\n"
|
||||||
|
@ -77,5 +77,5 @@
|
||||||
(doseq [[k v] (map identity (nth semver-test-data 3))]
|
(doseq [[k v] (map identity (nth semver-test-data 3))]
|
||||||
(testing (format "version-level %s" (name k))
|
(testing (format "version-level %s" (name k))
|
||||||
(is (= v (version-map->string
|
(is (= v (version-map->string
|
||||||
(increment-version
|
(bump-version
|
||||||
(nth semver-test-data 1) k))))))))))
|
(nth semver-test-data 1) k))))))))))
|
||||||
|
|
Loading…
Reference in a new issue