fringe2 files changed, 51 insertions(+)
gnu/packages.scm               |  1 +
gnu/services/configuration.scm | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++

fringemodified   gnu/packages.scm
fringe@@ -49,6 +49,7 @@ (define-module (gnu packages)
   #:export (search-patch
             search-patches
             search-auxiliary-file
+            %distro-root-directory
             %patch-path
             %auxiliary-files-path
             %package-module-path
fringemodified   gnu/services/configuration.scm
fringe@@ -25,6 +25,9 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu services configuration)
+  #:use-module (gnu packages)
+  #:use-module (guix discovery)
+  #:use-module (guix memoization)
   #:use-module (guix packages)
   #:use-module (guix records)
   #:use-module (guix gexp)
fringe@@ -34,6 +37,7 @@ (define-module (gnu services configuration)
                           warning))
   #:use-module ((guix modules) #:select (file-name->module-name))
   #:use-module (guix i18n)
+  #:use-module ((guix ui) #:select (warn-about-load-error))
   #:autoload   (texinfo) (texi-fragment->stexi)
   #:autoload   (texinfo serialize) (stexi->texi)
   #:use-module (ice-9 curried-definitions)
fringe@@ -588,3 +592,49 @@ (define (generic-serialize-alist combine serialize-field fields)
 @code{append} are usually good candidates for this."
   (apply combine
          (map (generic-serialize-alist-entry serialize-field) fields)))
+
+
+;;;
+;;; Configuration objects discovery.
+;;;
+
+(define %default-service-module-path
+  ;; Default search path for service modules.
+  `((,%distro-root-directory . "gnu/services")))
+
+(define (define-configuration? module symbol)
+  "Predicate to check if SYMBOL points to a `define-configuration'-generated
+object in MODULE."
+  (let ((fields-variable-name (symbol-append symbol '-fields)))
+    (or (module-local-variable module fields-variable-name) ;private variable
+        (module-variable module fields-variable-name))))    ;public variable
+
+(define (interface->directory interface)
+  "Convert a module interface to a module directory."
+  (resolve-module (module-name interface)))
+
+(define* (fold-configurations proc init
+                              #:optional
+                              (modules
+                               (map interface->directory
+                                    (all-modules %default-service-module-path
+                                                 #:warn
+                                                 warn-about-load-error)))
+                              #:key (select? (const #t)))
+  "Call (PROC MODULE SYMBOL RESULT) for each service configuration defined via
+`define-configuration' in the MODULES that matches SELECT?, using INIT as the
+initial value of RESULT.  SELECT? is called with two arguments, the module
+object as well as the variable name (a symbol) of the configuration record
+constructor, e.g. @code{'forgejo-configuration}."
+  ;; FIXME: Contrary to its name, `fold-module-public-variables*' (and
+  ;; fold-module-public-variables) fold all the variables of a module,
+  ;; including the private ones.  The distinction between public/private is
+  ;; made by whether the MODULES provided are whole modules (resolve-module)
+  ;; or just their exported interface (resolve-interface).
+  (fold-module-public-variables* (lambda (module symbol _ result)
+                                   (if (and (define-configuration? module symbol)
+                                            (select? module symbol))
+                                       (proc module symbol result)
+                                       result))
+                                 init
+                                 modules))

[back]

Generated by apteryx using scpaste at Wed May 27 23:10:50 2026. JST. (original)