Skip to content

Commit

Permalink
Add default behaviour to bump version
Browse files Browse the repository at this point in the history
  • Loading branch information
just-sultanov committed Jan 19, 2024
1 parent 175f28f commit 3c5a687
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 48 deletions.
47 changes: 22 additions & 25 deletions src/main/clojure/xdeps/api/version/semantic.clj
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
(ns xdeps.api.version.semantic
(:require
[clojure.string :as str]
[malli.core :as m])
[clojure.string :as str]
[malli.core :as m])
(:import
(java.io
Writer)))

(java.io
Writer)))

(set! *warn-on-reflection* true)


(def Version
[:map
[:major [:int {:min 0}]]
Expand All @@ -18,7 +16,6 @@
[:pre-release [:maybe string?]]
[:build [:maybe string?]]])


(def re
(->> ["^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)"
"(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)"
Expand All @@ -27,57 +24,57 @@
(str/join)
(re-pattern)))


(defprotocol ISemanticVersion
(valid? [x] "Returns `true` if 'x` satisfies the semantic version.")
(parse [x] "Returns an instance of `xdeps.api.version.semantic/SemanticVersion` if `x` satisfies the semantic version. Otherwise, returns `nil`.")
(bump [x part] "Returns an instance of `xdeps.api.version.semantic/SemanticVersion` with the incremented part (`:major`, `:minor` or `:patch`)."))

(bump [x] [x part] "Returns an instance of `xdeps.api.version.semantic/SemanticVersion` with the incremented part (`:major`, `:minor` or `:patch`)."))

(defrecord SemanticVersion
[major minor patch pre-release build]
(defrecord SemanticVersion [major minor patch pre-release build]
ISemanticVersion
(valid? [v] (m/validate Version v))
(parse [v] v)
(bump [v] (bump v :patch))
(bump [v part]
(case part
:major (-> v (update :major inc) (assoc :minor 0 :patch 0))
:minor (-> v (update :minor inc) (assoc :patch 0))
:patch (update v :patch inc)
(throw (ex-info (format "Can't bump %s version" part) {:given part, :allowed #{:major :minor :patch}}))))

(throw (ex-info (format "Can't bump %s version" part) {:given part,
:allowed #{:major :minor :patch}}))))
Object
(toString [_]
(toString
[_]
(cond-> (format "%s.%s.%s" major minor patch)
pre-release (str "-" pre-release)
build (str "+" build))))


(defmethod print-method SemanticVersion
[v ^Writer w]
(print-method (into {} v) w))


(defmethod print-dup SemanticVersion
[v ^Writer w]
(print-method v w))


(extend-protocol ISemanticVersion
nil
(valid? [_] false)
(parse [_] nil)
(bump [_ _] nil)
(bump
([_] nil)
([_ _] nil))

String
(valid? [s] (->> s (re-matches re) (boolean)))
(parse [s]
(when (valid? s)
(let [[[_s major minor patch pre-release build]] (re-seq re s)]
(map->SemanticVersion
{:major (parse-long major)
:minor (parse-long minor)
:patch (parse-long patch)
:pre-release pre-release
:build build}))))
(bump [s part] (-> s (parse) (bump part))))
{:major (parse-long major)
:minor (parse-long minor)
:patch (parse-long patch)
:pre-release pre-release
:build build}))))
(bump
([s] (bump s :patch))
([s part] (-> s (parse) (bump part) (str)))))
80 changes: 57 additions & 23 deletions src/test/clojure/xdeps/api/version/semantic_test.clj
Original file line number Diff line number Diff line change
@@ -1,34 +1,68 @@
(ns xdeps.api.version.semantic-test
(:require
[clojure.test :refer [deftest testing is]]
[xdeps.api.version.semantic :as sut]))
[clojure.test :refer [deftest is testing]]
[xdeps.api.version.semantic :as sut]))


(deftest parse-test
(deftest ^:unit parse-test
(testing "correct conversion to a string"
(doseq [v ["0.1.0"
"0.1.0-SNAPSHOT"
"0.1.0+master-bb1023"
"0.1.0-alpha+master-bb1023"]]
(is (= v (str (sut/parse v)))))))


(deftest bump-test
(deftest ^:unit bump-test
(testing "correct version bump"
(testing "major version"
(let [v (sut/bump "0.1.2" :major)]
(is (= "1.0.0" (str v)))
(is (= {:major 1, :minor 0, :patch 0, :pre-release nil, :build nil}
(into {} v)))))

(testing "minor version"
(let [v (sut/bump "0.1.2" :minor)]
(is (= "0.2.0" (str v)))
(is (= {:major 0, :minor 2, :patch 0, :pre-release nil, :build nil}
(into {} v)))))

(testing "patch version"
(let [v (sut/bump "0.1.2" :patch)]
(is (= "0.1.3" (str v)))
(is (= {:major 0, :minor 1, :patch 3, :pre-release nil, :build nil}
(into {} v)))))))

(testing "string -> string"
(testing "major version"
(is (= "1.0.0" (sut/bump "0.1.2" :major))))

(testing "minor version"
(is (= "0.2.0" (sut/bump "0.1.2" :minor))))

(testing "patch version"
(is (= "0.1.3"
(sut/bump "0.1.2")
(sut/bump "0.1.2" :patch)))))

(testing "semantic version -> semantic version"
(testing "major version"
(let [v (-> "0.1.2"
(sut/parse)
(sut/bump :major))]
(is (= "1.0.0" (str v)))
(is (= {:major 1
:minor 0
:patch 0
:pre-release nil
:build nil}
(into {} v)))))

(testing "minor version"
(let [v (-> "0.1.2"
(sut/parse)
(sut/bump :minor))]
(is (= "0.2.0" (str v)))
(is (= {:major 0
:minor 2
:patch 0
:pre-release nil
:build nil}
(into {} v)))))

(testing "patch version"
(let [v1 (-> "0.1.2"
(sut/parse)
(sut/bump))
v2 (-> "0.1.2"
(sut/parse)
(sut/bump :patch))]
(is (= "0.1.3" (str v1) (str v2)))
(is (= {:major 0
:minor 1
:patch 3
:pre-release nil
:build nil}
(into {} v1)
(into {} v2))))))))

0 comments on commit 3c5a687

Please sign in to comment.