version.lisp 4.26 KB
Newer Older
Eric Timmons's avatar
Eric Timmons committed
1
2
3
4
5
;;;; CLPM version definitions
;;;;
;;;; This software is part of CLPM. See README.org for more information. See
;;;; LICENSE for license information.

6
(uiop:define-package #:clpm/version
7
8
    (:use #:cl
          #:clpm/version-strings)
9
10
11
12
13
14
15
16
17
  (:export #:clpm-version))

(in-package #:clpm/version)


;;; Application Version

;; NOTE: If this form changes position in this file you *must* update clpm.asd as
;; well.
Eric Timmons's avatar
Eric Timmons committed
18
(defparameter *version-for-asdf* "0.3.0"
Eric Timmons's avatar
Eric Timmons committed
19
20
21
  "ASDF is overly picky about its version numbers. This should be the primary
  version number (no prerelease info) as ~*base-version*~.")

Eric Timmons's avatar
Eric Timmons committed
22
(defparameter *base-version* "0.3.0-alpha.4"
23
  "The base version number of CLPM.")
24

25
26
27
(defparameter *full-version* nil
  "Cache the full version information as of when the executable was built. Is
NIL until an image is dumped and is set by ~cache-full-version~.")
28
29
30
31
32

(defun git-exists-p ()
  "Returns T iff git exists and is callable."
  (ignore-errors
   (uiop:run-program '("git" "--version"))
33
   (clpm-git '("describe"))
34
35
   t))

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
(defun clpm-git (args &rest keys)
  (uiop:with-current-directory ((asdf:system-relative-pathname :clpm ""))
    (apply #'uiop:run-program
           `("git" ,@args)
           keys)))

(defun get-git-branch ()
  (or
   (ignore-errors
    (clpm-git '("symbolic-ref" "--short" "HEAD")
              :output '(:string :stripped t)))
   "HEAD"))

(defun get-git-commit ()
  (clpm-git '("rev-parse" "--short" "HEAD")
            :output '(:string :stripped t)))

(defun get-git-dirty-p ()
  (not (zerop (nth-value 2
                         (clpm-git '("diff-index" "--quiet" "HEAD")
                                   :ignore-error-status t)))))

(defun get-git-describe (&optional ref)
59
  (uiop:split-string
60
   (clpm-git `("describe" "--tags" "--match" "v*" ,@(when ref (list ref)))
61
62
63
             :output '(:string :stripped t))
   :max 3
   :separator '(#\-)))
64
65
66
67
68
69
70
71
72

(defun get-git-common-ancestor ()
  (clpm-git '("merge-base" "HEAD" "master")
            :output '(:string :stripped t)))

(defun get-git-distance-from-master ()
  (parse-integer (clpm-git '("rev-list" "--count" "HEAD" "--not" "master")
                           :output '(:string :stripped t))))

73
74
75
76
(defun get-git-tag-p ()
  (zerop (nth-value 2
                    (clpm-git '("describe" "--tags" "--exact-match" "HEAD")
                              :ignore-error-status t))))
77
78
79
80
81
82

(defun get-full-version ()
  (if (git-exists-p)
      (let ((git-branch (get-git-branch))
            (git-describe (get-git-describe))
            (git-dirty-p (get-git-dirty-p)))
83
        (if (get-git-tag-p)
84
85
86
            ;; This is a tagged version, just return the base version number.
            *base-version*
            ;; Here's the fun part, assemble the entire version string.
Eric Timmons's avatar
Eric Timmons committed
87
88
89
90
91
92
93
94
95
            (destructuring-bind (primary-version prerelease-category build-meta)
                (parse-semantic-version *base-version*)
              (declare (ignore build-meta))
              (unless prerelease-category
                (setf prerelease-category '(0)))
              (if (equal git-branch "master")
                  (format nil "~{~A~^.~}-~{~A~^.~}.~A+~A~:[~;-dirty~]"
                          primary-version
                          prerelease-category
96
97
                          (second git-describe)
                          (third git-describe)
Eric Timmons's avatar
Eric Timmons committed
98
99
100
101
                          git-dirty-p)
                  (let* ((ancestor (get-git-common-ancestor))
                         (ancestor-describe (get-git-describe ancestor))
                         (distance-from-master (get-git-distance-from-master)))
Eric Timmons's avatar
Eric Timmons committed
102
103
                    (format nil "~{~A~^.~}-~{~A~^.~}.~A.0.~A.~A+~A~:[~;-dirty~]"
                            primary-version prerelease-category
104
                            (second ancestor-describe)
Eric Timmons's avatar
Eric Timmons committed
105
106
                            git-branch
                            distance-from-master
107
                            (third git-describe)
Eric Timmons's avatar
Eric Timmons committed
108
                            git-dirty-p))))))
109
110
111
112
113
114
115
116
      ;; We don't have git... Best we can currently do is return the base
      ;; version number.
      *base-version*))

(defun cache-full-version ()
  "Cache the full version into ~*full-version*~."
  (setf *full-version* (get-full-version)))
(uiop:register-image-dump-hook 'cache-full-version)
117
118

(defun clpm-version ()
119
  "Return the CLPM version string."
120
121
122
  (or
   *full-version*
   (get-full-version)))