aboutsummaryrefslogtreecommitdiff
path: root/src/property.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/property.lisp')
-rw-r--r--src/property.lisp32
1 files changed, 32 insertions, 0 deletions
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))))