From: Bruno Victal <mirai@makinata.eu>
To: 63985@debbugs.gnu.org
Cc: Bruno Victal <mirai@makinata.eu>
Subject: [bug#63985] [PATCH RFC v2 5/5] services: configuration: New generic-ini module.
Date: Sat, 10 Jun 2023 21:10:56 +0100 [thread overview]
Message-ID: <59632edef13e9ed3f922e67142a6288e995c5bef.1686427611.git.mirai@makinata.eu> (raw)
In-Reply-To: <cover.1686343642.git.mirai@makinata.eu>
Implements a ‘serialize-ini-configuration’ procedure for serializing
record-types defined with define-configuration into generic INI files.
* gnu/services/configuration/generic-ini.scm: New module.
* tests/services/configuration/generic-ini.scm: Add tests for new module.
* Makefile.am: Register tests.
* gnu/local.mk: Register module.
---
Makefile.am | 1 +
gnu/local.mk | 1 +
gnu/services/configuration/generic-ini.scm | 129 +++++++++++++++++++
tests/services/configuration/generic-ini.scm | 103 +++++++++++++++
4 files changed, 234 insertions(+)
create mode 100644 gnu/services/configuration/generic-ini.scm
create mode 100644 tests/services/configuration/generic-ini.scm
diff --git a/Makefile.am b/Makefile.am
index ab901df757..8dc9a3438b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -552,6 +552,7 @@ SCM_TESTS = \
tests/services.scm \
tests/services/file-sharing.scm \
tests/services/configuration.scm \
+ tests/services/configuration/generic-ini.scm \
tests/services/lightdm.scm \
tests/services/linux.scm \
tests/services/telephony.scm \
diff --git a/gnu/local.mk b/gnu/local.mk
index ce16d37e2b..a05d70aff3 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -670,6 +670,7 @@ GNU_SYSTEM_MODULES = \
%D%/services/cgit.scm \
%D%/services/ci.scm \
%D%/services/configuration.scm \
+ %D%/services/configuration/generic-ini.scm \
%D%/services/cuirass.scm \
%D%/services/cups.scm \
%D%/services/databases.scm \
diff --git a/gnu/services/configuration/generic-ini.scm b/gnu/services/configuration/generic-ini.scm
new file mode 100644
index 0000000000..88d145bc50
--- /dev/null
+++ b/gnu/services/configuration/generic-ini.scm
@@ -0,0 +1,129 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu services configuration generic-ini)
+ #:use-module (gnu services configuration)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-171)
+ #:use-module (ice-9 match)
+ #:export (ini-entry?
+ list-of-ini-entries?
+
+ serialize-ini-configuration))
+
+;;;
+;;; Generic INI serializer
+;;;
+
+\f
+;;;
+;;; Predicates
+;;;
+
+;; This is the same format used in SRFI-233 but without comment support.
+(define ini-entry?
+ (match-lambda
+ (((? symbol?) (? symbol?) (? string?)) #t)
+ (_ #f)))
+
+(define list-of-ini-entries?
+ (list-of ini-entry?))
+
+;;
+;; Overall design document
+;;
+;; This module implements a generic INI serializer for a record-type defined
+;; using define-configuration.
+;; It expects that the serialize-<type> procedures return a list with
+;; three elements of the form:
+;; (list section key value)
+;; Where ‘section’ and ‘key’ are symbols and ‘value’ is a string.
+;; The fields within define-configuration do not have to be ordered in,
+;; any way whatsoever as the ‘serialize-ini’ will group them up automatically.
+;; This implies that no assumptions should be made regarding the order of the
+;; values in the serializied INI output.
+;;
+;; Additional notes:
+;; Q: Why not replace rcons with string-append and forego the ungexp-splice?
+;; A: The transduction happens outside of the G-Exp while the final string-append
+;; takes place in the G-Exp.
+;;
+;; Debugging tips: Open a REPL and try one transducer at a time from
+;; ‘ini-transducer’.
+;;
+
+(define (add-section-header partition)
+ (let ((header (caar partition)))
+ (cons (list header)
+ partition)))
+
+(define serializer
+ (match-lambda
+ ((section)
+ #~(format #f "[~a]~%" '#$section))
+ ((section key value)
+ #~(format #f "~a=~a~%" '#$key #$value))
+ ;; Used for the newline between sections.
+ ('*section-separator* "\n")))
+
+(define ini-transducer
+ (compose (tpartition car)
+ (tmap add-section-header)
+ (tadd-between '(*section-separator*))
+ tconcatenate
+ (tmap serializer)))
+
+;; A “first-pass” serialization is performed and sorted in order
+;; to group up the fields by “section” before passing through the
+;; transducer.
+(define (serialize-ini-configuration config fields)
+ (let* ((srfi-233-IR
+ ;; First pass: “serialize” into a (disordered) list of
+ ;; SRFI-233 entries.
+ (list-transduce (base-transducer config) rcons fields))
+ (comparator (lambda (x y)
+ ;; Sort the SRFI-233 entries by section.
+ (string<=? (symbol->string (car x))
+ (symbol->string (car y)))))
+ (sorted-entries (sort srfi-233-IR comparator)))
+ #~(string-append
+ #$@(list-transduce ini-transducer rcons sorted-entries))))
+
+;; FIXME:RFC:
+;; generic-ini- prefixed serializing procs?
+;; (perhaps prefixed as generic-ini: ?)
+;; Example procedures:
+;;
+(define* (generic-ini-serialize-string field-name value #:key section)
+ (list section field-name value))
+
+;; field-name-transform can be used to “uglify” a field-name,
+;; e.g. want-ipv6? -> want_ipv6
+(define* (generic-ini-serialize-boolean field-name value #:key section
+ (field-name-transform identity))
+ (list section (field-name-transform field-name)
+ (if value "true" "false")))
+
+
+;;; FIXME: delete this before inclusion, these are notes for the first RFC.
+;;;
+;;; Left out for now (but readily extendable):
+;;; * Custom leading (presumed to be whitespace) characters for entries
+;;; à la gitconfig, mostly pretty-printing purposes
+;;; * Configurable delimiter (\n, \r\n, \0, ...)
+;;; * Configurable Key-value separator (this is usually =)
diff --git a/tests/services/configuration/generic-ini.scm b/tests/services/configuration/generic-ini.scm
new file mode 100644
index 0000000000..3bdf0e12c2
--- /dev/null
+++ b/tests/services/configuration/generic-ini.scm
@@ -0,0 +1,103 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (tests services configuration generic-ini)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu services configuration generic-ini)
+ #:use-module (guix diagnostics)
+ #:use-module (guix gexp)
+ #:use-module (guix store)
+ #:autoload (guix i18n) (G_)
+ #:use-module (srfi srfi-34)
+ #:use-module (srfi srfi-64)
+ #:use-module (srfi srfi-71))
+
+;;; Tests for the (gnu services configuration generic-ini) module.
+
+(test-begin "generic-ini serializer")
+
+
+(define expected-output "\
+[ranch]
+shepherd=Emma
+
+[shed]
+enabled=true
+capacity=50
+production=wool
+")
+
+\f
+;;;
+;;; Serializers
+;;;
+(define (strip-trailing-?-character field-name)
+ "Drop rightmost '?' character"
+ (let ((str (symbol->string field-name)))
+ (if (string-suffix? "?" str)
+ (string->symbol (string-drop-right str 1))
+ field-name)))
+
+(define* (serialize-string field-name value #:key section)
+ (list section field-name value))
+
+(define* (serialize-number field-name value #:key section)
+ (list section field-name (number->string value)))
+
+(define* (serialize-boolean field-name value #:key section)
+ (list section (strip-trailing-?-character field-name)
+ (if value "true" "false")))
+
+\f
+;;;
+;;; Record-type definition
+;;;
+
+(define-configuration foo-configuration
+ (production
+ (string "wool")
+ "Lorem Ipsum …"
+ (serializer-options '(#:section shed)))
+
+ (capacity
+ (number 50)
+ "Lorem Ipsum …"
+ (serializer-options '(#:section shed)))
+
+ (enabled?
+ (boolean #t)
+ "Lorem Ipsum …"
+ (serializer-options '(#:section shed)))
+
+ (shepherd
+ (string "Emma")
+ "Lorem Ipsum …"
+ (serializer-options '(#:section ranch))))
+
+(test-equal "Well-formed INI output from serialize-ini"
+ expected-output
+ ;; Serialize the above into a string, properly resolving any potential
+ ;; nested G-Exps as well.
+ (let* ((serialized-ini
+ (serialize-ini-configuration (foo-configuration)
+ foo-configuration-fields))
+ (lowered conn (with-store store
+ ((lower-gexp serialized-ini) store))))
+ (eval (lowered-gexp-sexp lowered) (current-module))))
+
+(test-end)
--
2.39.2
next prev parent reply other threads:[~2023-06-10 20:18 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-09 21:18 [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Bruno Victal
2023-06-09 21:20 ` [bug#63985] [PATCH RFC 1/5] services: configuration: Simplify normalize-extra-args Bruno Victal
2023-06-09 21:20 ` [bug#63985] [PATCH RFC 2/5] services: configuration: Use transducers within serialize-configuration Bruno Victal
2023-06-09 21:20 ` [bug#63985] [PATCH RFC 3/5] services: fstrim-service-type: Serialize with SRFI-171 transducers Bruno Victal
2023-06-09 21:20 ` [bug#63985] [PATCH RFC 4/5] services: configuration: Add serializer-kwargs field Bruno Victal
2023-06-09 21:21 ` [bug#63985] [PATCH RFC 5/5] services: configuration: New generic-ini module Bruno Victal
2023-06-10 20:10 ` [bug#63985] [PATCH RFC v2 1/5] services: configuration: Simplify normalize-extra-args Bruno Victal
2023-06-10 20:10 ` [bug#63985] [PATCH RFC v2 2/5] services: configuration: Use transducers within serialize-configuration Bruno Victal
2023-06-10 20:10 ` [bug#63985] [PATCH RFC v2 3/5] services: fstrim-service-type: Serialize with SRFI-171 transducers Bruno Victal
2023-06-10 20:10 ` [bug#63985] [PATCH RFC v2 4/5] services: configuration: Add serializer-options field Bruno Victal
2023-06-10 20:10 ` Bruno Victal [this message]
2023-06-26 21:57 ` [bug#63985] [PATCH v3 00/11] Service subsystem improvements Bruno Victal
2023-06-26 21:59 ` [bug#63985] [PATCH v3 01/11] services: configuration: Simplify normalize-extra-args Bruno Victal
2023-10-02 17:00 ` [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Maxim Cournoyer
2023-10-07 12:36 ` [bug#63985] [PATCH v3 01/11] services: configuration: Simplify normalize-extra-args. (was: bug#63985: [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration) Bruno Victal
2023-06-26 21:59 ` [bug#63985] [PATCH v3 02/11] services: configuration: Use transducers within serialize-configuration Bruno Victal
2023-10-02 17:25 ` [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Maxim Cournoyer
2023-10-07 13:39 ` [bug#63985] [PATCH v3 02/11] services: configuration: Use transducers within serialize-configuration. (was : bug#63985: [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration) Bruno Victal
2023-10-07 14:37 ` Maxim Cournoyer
2023-06-26 21:59 ` [bug#63985] [PATCH v3 03/11] services: fstrim-service-type: Serialize with SRFI-171 transducers Bruno Victal
2023-06-26 21:59 ` [bug#63985] [PATCH v3 04/11] doc: Rewrite define-configuration Bruno Victal
2023-10-02 18:28 ` [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Maxim Cournoyer
2023-10-07 14:21 ` Bruno Victal
2023-10-07 16:35 ` Maxim Cournoyer
2023-06-26 21:59 ` [bug#63985] [PATCH v3 05/11] services: configuration: Add serializer-options field Bruno Victal
2023-10-02 19:12 ` [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Maxim Cournoyer
2023-10-06 18:29 ` Bruno Victal
2023-06-26 21:59 ` [bug#63985] [PATCH v3 06/11] services: configuration: New generic-ini module Bruno Victal
2023-10-02 19:15 ` [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Maxim Cournoyer
2023-06-26 21:59 ` [bug#63985] [PATCH v3 07/11] services: configuration: Add some commonly used predicates Bruno Victal
2023-06-26 21:59 ` [bug#63985] [PATCH v3 08/11] services: NetworkManager: Use define-configuration and generic-ini Bruno Victal
2023-06-26 21:59 ` [bug#63985] [PATCH v3 09/11] services: NetworkManager: Prefer package over network-manager Bruno Victal
2023-10-02 16:52 ` [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Maxim Cournoyer
2023-06-26 21:59 ` [bug#63985] [PATCH v3 10/11] services: NetworkManager: add log-configuration field Bruno Victal
2023-10-05 16:57 ` Maxim Cournoyer
2023-06-26 21:59 ` [bug#63985] [PATCH v3 11/11] services: NetworkManager: Add extra-options field Bruno Victal
2023-10-05 16:59 ` Maxim Cournoyer
2023-06-27 4:20 ` [bug#63985] [PATCH v3 00/11] Service subsystem improvements Liliana Marie Prikler
2023-09-16 21:22 ` Bruno Victal
2023-09-16 21:55 ` Liliana Marie Prikler
2023-09-23 13:35 ` Bruno Victal
2023-09-23 15:22 ` Liliana Marie Prikler
2023-09-25 14:06 ` Ludovic Courtès
2023-10-07 15:57 ` [bug#63985] [PATCH v4 0/5] SRFI-171 based improvements for define-configuration Bruno Victal
2023-10-07 15:57 ` [bug#63985] [PATCH v4 2/5] services: configuration: Use transducers within serialize-configuration Bruno Victal
2023-10-07 15:59 ` [bug#63985] [PATCH v4 1/5] services: configuration: Simplify normalize-extra-args Bruno Victal
2023-10-07 15:59 ` [bug#63985] [PATCH v4 3/5] services: fstrim-service-type: Serialize with SRFI-171 transducers Bruno Victal
2023-10-07 15:59 ` [bug#63985] [PATCH v4 4/5] doc: Rewrite define-configuration Bruno Victal
2023-10-07 15:59 ` [bug#63985] [PATCH v4 5/5] services: configuration: Add some commonly used predicates Bruno Victal
2023-10-07 16:57 ` bug#63985: SRFI-171 based improvements for define-configuration Maxim Cournoyer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=59632edef13e9ed3f922e67142a6288e995c5bef.1686427611.git.mirai@makinata.eu \
--to=mirai@makinata.eu \
--cc=63985@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).