diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2021-05-03 17:23:21 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2021-05-06 12:23:51 -0700 |
commit | 9e5770606c30cb8b763a572aba59fac42484898c (patch) | |
tree | ea0ebc36d84deadd2e80a08e99107f9819b32e67 /src | |
parent | 0dba628638acd2aa5d990cd1edd41ac689f808c8 (diff) | |
download | consfigurator-9e5770606c30cb8b763a572aba59fac42484898c.tar.gz |
factor out FILE:UPDATE-UNIX-TABLE
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'src')
-rw-r--r-- | src/package.lisp | 3 | ||||
-rw-r--r-- | src/property/file.lisp | 32 | ||||
-rw-r--r-- | src/property/fstab.lisp | 29 |
3 files changed, 35 insertions, 29 deletions
diff --git a/src/package.lisp b/src/package.lisp index de9eb85..edd90ca 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -260,7 +260,8 @@ #:regex-replaced-lines #:directory-exists #:symlinked - #:is-copy-of)) + #:is-copy-of + #:update-unix-table)) (defpackage :consfigurator.property.os (:use #:cl #:consfigurator) diff --git a/src/property/file.lisp b/src/property/file.lisp index 71372d8..dd4ae89 100644 --- a/src/property/file.lisp +++ b/src/property/file.lisp @@ -409,3 +409,35 @@ removed, and semicolon comment chars will be replaced with '#'." finally (return (nconc new-lines (sort accum #'string< :key #'cadr))))))))))) + +(defun update-unix-table (file source target entries &key (no-source "none")) + "Ensure that the UNIX table at FILE (e.g. /etc/fstab) contains each of +ENTRIES, using a simple merge procedure: existing lines of the file with the +same value for the TARGETth field are updated to match the corresponding +members of ENTRIES, except that if the SOURCEth field of the existing entry is +not NO-SOURCE and the corresponding member of ENTRIES is STRING= to either +NO-SOURCE or \"PLACEHOLDER\", use the existing field value." + (let ((unknown (list no-source "PLACEHOLDER")) + (pending (make-hash-table :test #'equal))) + (flet ((fields (entry) + (remove "" (split-string entry) :test #'string=))) + (dolist (entry entries) + (setf (gethash (nth target (fields entry)) pending) entry)) + (map-file-lines + file + (lambda (lines) + (loop for line in lines + for line-fields = (fields line) + for line-source = (nth source line-fields) + and line-target = (nth target line-fields) + for entry = (when-let* ((entry (gethash line-target pending)) + (fields (fields entry))) + (and (member (nth source fields) + unknown :test #'string=) + (not (string= line-source no-source)) + (setf (nth source fields) line-source) + (format nil "~{~A~^ ~}" fields))) + if entry + collect it into accum and do (remhash line-target pending) + else collect line into accum + finally (return (nconc accum (hash-table-values pending))))))))) diff --git a/src/property/fstab.lisp b/src/property/fstab.lisp index f89365d..7be61a4 100644 --- a/src/property/fstab.lisp +++ b/src/property/fstab.lisp @@ -64,12 +64,6 @@ Other properties might fill it in." ;;;; Properties -(defun entry->source (entry) - (car (split-string entry))) - -(defun entry->mountpoint (entry) - (cadr (remove "" (split-string entry) :test #'string=))) - (defprop entries :posix (&rest entries) "Ensure that /etc/fstab contains each of ENTRIES, using a simple merge procedure: existing lines of the fstab with the same mount point as any of @@ -81,28 +75,7 @@ This makes it easy to update mount options without having to specify the partition or filesystem UUID in your consfig." (:desc (format nil "fstab entries for ~{~A~^, ~}" (mapcar #'entry->mountpoint entries))) - (:apply - (file:map-file-lines - #P"/etc/fstab" - (lambda (lines) - (let ((pending (make-hash-table :test #'equal))) - (dolist (entry entries) - (setf (gethash (entry->mountpoint entry) pending) entry)) - (loop for line in lines - for line-source = (entry->source line) - and line-mountpoint = (entry->mountpoint line) - for entry = (let ((entry (gethash line-mountpoint pending))) - (if (and (member (entry->source entry) - '("none" "PLACEHOLDER") - :test #'string=) - (not (string= line-source "none"))) - (format nil "~A ~{~A~^ ~}" - line-source (cdr (split-string entry))) - entry)) - if entry - collect it into accum and do (remhash line-mountpoint pending) - else collect line into accum - finally (return (nconc accum (hash-table-values pending))))))))) + (:apply (file:update-unix-table #P"/etc/fstab" 0 1 entries))) (defprop entries-for-volumes :posix () "Add or update entries in /etc/fstab for the host's volumes, as specified with |