aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ideas.rst5
-rw-r--r--src/package.lisp2
-rw-r--r--src/property.lisp32
3 files changed, 34 insertions, 5 deletions
diff --git a/doc/ideas.rst b/doc/ideas.rst
index d32ffed..1209e7d 100644
--- a/doc/ideas.rst
+++ b/doc/ideas.rst
@@ -49,11 +49,6 @@ Core
calling its :HOSTATTRS subroutine too -- could we figure out catching and
ignoring the condition when its :HOSTATTRS subroutine did get run?
-- Macro for use in DEFPROP which works like Propellor's changesFile. Will
- probably output ``(:check ...)`` expression and then substitute user's code
- into a ``(:apply ...)`` expression. Use this or variants thereof in most of
- the entries in ``PROPERTY.FILE``.
-
- HOSTDEPLOY and HOSTDEPLOY-THESE functions which are like DEPLOY and
DEPLOY-THESE but take the CONNECTION argument from the :DEPLOY argument to
DEFHOST.
diff --git a/src/package.lisp b/src/package.lisp
index 5631860..efce2ee 100644
--- a/src/package.lisp
+++ b/src/package.lisp
@@ -130,6 +130,8 @@
#:assert-euid-root
#:assert-connection-supports
#:call-with-os
+ #:with-change-if-changes-file
+ #:with-change-if-changes-file-content
;; propspec.lisp
#:in-consfig
diff --git a/src/property.lisp b/src/property.lisp
index 7ff6c92..4403eb7 100644
--- a/src/property.lisp
+++ b/src/property.lisp
@@ -468,3 +468,35 @@ apply or unapply properties.")
(unless (or (eq type :posix) (lisp-connection-p))
(failed-change
"Cannot apply :LISP properties using a POSIX-type connection")))
+
+(defun cksum (file)
+ (ignore-errors (parse-integer (car (split-string (mrun "cksum" file))))))
+
+;; this is a safe parse of ls(1) output given its POSIX specification
+(defun ls-cksum (file)
+ (let ((ls (ignore-errors
+ (split-string (mrun :env '(:LOCALE "C") "ls" "-dlL" file))))
+ (cksum (cksum file)))
+ (when (and ls cksum)
+ (list* (car ls) cksum (subseq ls 2 8)))))
+
+(defmacro with-change-if-changes-file ((file) &body forms)
+ "Execute FORMS and yield :NO-CHANGE if FILE does not change.
+Since stat(1) is not POSIX, this is implemented by calling `ls -dlL' and
+cksum(1), and seeing if any of the information reported there, except for the
+number of links, has changed. Thus, you should not use this macro to detect
+changes in properties which will change the file but not the output of `ls
+-dlL' and cksum(1)."
+ (with-gensyms (before)
+ `(let* ((,before (ls-cksum ,file))
+ (result (progn ,@forms)))
+ (if (and ,before (equal ,before (ls-cksum ,file)))
+ :no-change result))))
+
+(defmacro with-change-if-changes-file-content ((file) &body forms)
+ "Execute FORMS and yield :NO-CHANGE if FILE has the same content afterwards."
+ (with-gensyms (before)
+ `(let* ((,before (cksum ,file))
+ (result (progn ,@forms)))
+ (if (and ,before (eql ,before (cksum ,file)))
+ :no-change result))))