blob: ee4ea71fdea88c2578bd982745e611085be59eb0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
;;; Consfigurator -- Lisp declarative configuration management system
;;; Copyright (C) 2020-2021 Sean Whitton <spwhitton@spwhitton.name>
;;; This file is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3, or (at your option)
;;; any later version.
;;; This file is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(in-package :consfigurator)
(defun noop (&rest args)
"Accept any arguments and do nothing."
(declare (ignore args))
(values))
(defun lines (text)
(split-string (stripln text) :separator '(#\Newline #\Return)))
(defun unlines (lines)
(format nil "~{~A~%~}" lines))
(defmacro symbol-named (name symbol)
`(and (symbolp ,symbol)
(string= (symbol-name ',name) (symbol-name ,symbol))))
(defun normalise-system (system)
(etypecase system
(string system)
(symbol (string-downcase
(symbol-name system)))))
(defun memstring= (string list)
(member string list :test #'string=))
;;;; Version numbers
(defun version< (x y)
(dpkg-version-compare x "<<" y))
(defun version> (x y)
(dpkg-version-compare x ">>" y))
(defun version<= (x y)
(dpkg-version-compare x "<=" y))
(defun version>= (x y)
(dpkg-version-compare x ">=" y))
(defun dpkg-version-compare (x r y)
(zerop (nth-value 2 (run-program `("dpkg" "--compare-versions"
,(etypecase x
(string x)
(number (format nil "~A" x)))
,r
,(etypecase y
(string y)
(number (format nil "~A" y))))
:ignore-error-status t))))
;;;; Encoding of strings to filenames
;; Encoding scheme based on one by Joey Hess -- File.configFileName in
;; propellor. Try to avoid including non-alphanumerics other than '.' and '_'
;; in the filename, such that it both remains roughly human-readable and is
;; likely to be accepted by programs which don't treat filenames as opaque
;; (and interpret them with a charset sufficiently similar to Lisp's).
;; This implementation also assumes that the Lisp doing the decoding has the
;; same charset as the Lisp doing the encoding.
(defun string->filename (s)
(apply #'concatenate 'string
(loop for c
across (etypecase s (string s) (number (write-to-string s)))
if (or (char= c #\.)
(alpha-char-p c)
(digit-char-p c))
collect (format nil "~C" c)
else
collect (format nil "_~X_" (char-code c)))))
(defun filename->string (s)
(loop with decoding
with buffer
with result
for c across s
do (cond
((and (char= c #\_) (not decoding))
(setq decoding t))
((and (char= c #\_) decoding)
(unless buffer (error "invalid encoding"))
(push (code-char
(read-from-string
(coerce (cons #\# (cons #\x (nreverse buffer)))
'string)))
result)
(setq buffer nil
decoding nil))
(decoding
(push c buffer))
(t
(push c result)))
finally (return (coerce (nreverse result) 'string))))
|