From a6b692fc167b8fa7fbdf4ac821fdb23a7295a8cc Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 27 Mar 2021 20:41:40 -0700 Subject: add WITH-CHANGE-IF-CHANGES-FILE{,-CONTENT} Signed-off-by: Sean Whitton --- doc/ideas.rst | 5 ----- src/package.lisp | 2 ++ src/property.lisp | 32 ++++++++++++++++++++++++++++++++ 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)))) -- cgit v1.2.3