home: Add fold-home. * home.scm (fold-home): New procedure. (user-home, home-type, home-extension, home-extension-point) (base-home-configuration): New data types. (root-home-type): New variable. * doc: Update every document to the new home-type syntax. * home/hexchat.scm (hexchat-home-type): New variable. * home/keepassxc.scm (keepassxc-home-type): New variable. * home/openbox.scm (openbox-home-type): New variable. * home/ssh.scm (ssh-home-type): New variable. * home/utils.scm (simple-file-home, symlink-file-home): Return a user-home.
doc/README.md
| 39 | 39 | (home | |
| 40 | 40 | (data-directory "/data/alice") | |
| 41 | 41 | (configurations | |
| 42 | - | (list (something-home ...) | |
| 43 | - | (something-else-home ...) | |
| 44 | - | (other-stuff-home ...) | |
| 45 | - | (yet-another-config-home ...) | |
| 46 | - | ...))) | |
| 42 | + | (list | |
| 43 | + | (user-home something-home-type ...) | |
| 44 | + | (user-home something-else-home-type ...) | |
| 45 | + | (user-home other-stuff-home-type ...) | |
| 46 | + | (user-home yet-another-config-home-type ...) | |
| 47 | + | ...))) | |
| 47 | 48 | ``` | |
| 48 | 49 | ||
| 49 | 50 | #### Desktop and Window Managers |
doc/general.md
| 22 | 22 | (simple-file-home (local-file "gitconfig") ".gitconfig") | |
| 23 | 23 | ``` | |
| 24 | 24 | ||
| 25 | - | **Scheme Procedure**: (symlink-file-home from to) | |
| 25 | + | **Scheme Procedure**: (symlink-file-home to from) | |
| 26 | 26 | ||
| 27 | 27 | Create a symlink from the user home at _from_ that points to _to_. For instance, | |
| 28 | 28 | if you want to create a symlink to a file that can change over time, you can |
doc/hexchat.md
| 11 | 11 | ------------------ | |
| 12 | 12 | ||
| 13 | 13 | The main configuration is not complete compared to the configuration possibilities | |
| 14 | - | of the client. It currently only implements a very minimal set of configurations | |
| 14 | + | of the client. It currently only implements a very minimal set of configurations | |
| 15 | 15 | that are required for it to work properly. | |
| 16 | 16 | ||
| 17 | - | **Scheme Procedure**: (hexchat-home config) | |
| 17 | + | **Scheme Variable**: hexchat-home-type | |
| 18 | 18 | ||
| 19 | - | Generates configuration files for hexchat, according to config, an | |
| 20 | - | hexchat-configuration object. | |
| 19 | + | The type of the service that generates configuration files for hexchat. Its | |
| 20 | + | value is an hexchat-configuration object. | |
| 21 | 21 | ||
| 22 | 22 | **Data Type**: hexchat-configuration | |
| 23 | 23 | ||
… | |||
| 33 | 33 | ------- | |
| 34 | 34 | ||
| 35 | 35 | ```scheme | |
| 36 | - | (hexchat-home | |
| 37 | - | (hexchat-configuration | |
| 38 | - | (servlist | |
| 39 | - | (list | |
| 40 | - | (hexchat-server | |
| 41 | - | (name "R??zosup") | |
| 42 | - | (servers '("irc.rezosup.org/6697")) | |
| 43 | - | (flags '(cycle global honor-proxy ssl favorite | |
| 44 | - | allow-invalid-certificates))))) | |
| 45 | - | (log-dir "/data/alice/.local/share/hexchat/logs") | |
| 46 | - | (scrollback-dir "/data/alice/.local/share/hexchat/scrollback"))) | |
| 36 | + | (user-home | |
| 37 | + | hexchat-home-type | |
| 38 | + | (hexchat-configuration | |
| 39 | + | (servlist | |
| 40 | + | (list | |
| 41 | + | (hexchat-server | |
| 42 | + | (name "R??zosup") | |
| 43 | + | (servers '("irc.rezosup.org/6697")) | |
| 44 | + | (flags '(cycle global honor-proxy ssl favorite | |
| 45 | + | allow-invalid-certificates))))) | |
| 46 | + | (log-dir "/data/alice/.local/share/hexchat/logs") | |
| 47 | + | (scrollback-dir "/data/alice/.local/share/hexchat/scrollback"))) | |
| 47 | 48 | ``` | |
| 48 | 49 | ||
| 49 | 50 | ||
… | |||
| 74 | 75 | automatically connect to this network when hexchat is started, _honor-proxy_ | |
| 75 | 76 | to honor system-wide proxy configuration, _allow-invalid-certificates_ to | |
| 76 | 77 | allow invalid certificates (self-signed, expired, ...) and _favorite_ to add | |
| 77 | - | it to the list of favorite networks. | |
| 77 | > | ||
| 78 | 0 | > | \ No newline at end of file |
| 78 | + | it to the list of favorite networks. | |
doc/home.md
| 32 | 32 | (home hexchat)) | |
| 33 | 33 | ``` | |
| 34 | 34 | ||
| 35 | - | **Scheme Procedure**: (home basedir inputs #:guix-symlink #:guix-config-symlink #:local-symlink #:cache-symlink)) | |
| 35 | + | **Data Type**: home | |
| 36 | 36 | ||
| 37 | - | Create a package that can then be installed with `guix package -f` from _inputs_ | |
| 38 | - | and essential configuration. _inputs_ must be a list of inputs, namely a list | |
| 39 | - | of file-like objects. The resulting package is a union of all the inputs, with | |
| 40 | - | the addition of a few essential symlinks. | |
| 37 | + | This data type represents the configuration of a home directory. It is the | |
| 38 | + | type of the data a home configuration file must return. It is composed of | |
| 39 | + | the following fields: | |
| 41 | 40 | ||
| 42 | - | By default, when no input is given, and no keyword argument is used, these | |
| 43 | - | symlinks are created: | |
| 41 | + | * **data-directory**: The read-write directory that contains the user files. | |
| 42 | + | * **base-configuration** (default: a base-home-configuration object that takes | |
| 43 | + | the data-directory value into account, see below): A base-home-configuration | |
| 44 | + | object that contains configuration for required parts of the home configuration. | |
| 45 | + | * **configurations** (default: '()): A list of additional configurations. | |
| 46 | + | ||
| 47 | + | By default, when no base-configuration is given, the configuration contains | |
| 48 | + | instructions for these symlinks to be created: | |
| 44 | 49 | ||
| 45 | 50 | * `~/.guix-profile` ??? `${basedir}/.guix-profile` | |
| 46 | 51 | * `~/.config/guix` ??? `${basedir}/.config/guix` | |
| 47 | 52 | * `~/.local` ??? `${basedir}/.local` | |
| 48 | 53 | * `~/.cache` ??? `${basedir}/.cache` | |
| 49 | 54 | ||
| 50 | - | When the corresponding keyword argument is used, the associated path is used as | |
| 51 | - | the target of the symbolic link. | |
| 51 | > | ||
| 52 | 0 | > | \ No newline at end of file |
| 55 | + | **Data Type**: base-home-configuration | |
| 56 | + | ||
| 57 | + | This is the type of a basic home directory configuration that contains information | |
| 58 | + | for basic required configurations. It contains the following fields: | |
| 59 | + | ||
| 60 | + | * **guix-symlink**: The path to the default guix profile, in a read-write directory. | |
| 61 | + | * **guix-config-symlink**: The path to the configuration directory of guix. | |
| 62 | + | * **local-symlink**: The path to a read-write directory that corresponds to the | |
| 63 | + | .local directory. | |
| 64 | + | * **cache-symlink**: The path to a read-write directory that corresponds to the | |
| 65 | + | .cache directory. | |
| 66 | + | ||
| 67 | + | **Scheme Variable**: root-home-type | |
| 68 | + | ||
| 69 | + | The type of the root service, to which every service is folded. Its value | |
| 70 | + | is an association list that associates paths relative to the home directory | |
| 71 | + | with a path in the filesystem or a file-like object. | |
| 72 | + | ||
| 73 | + | It also contains a default extension point, whose value must be an association | |
| 74 | + | list that is concatenated to the already configured association list. |
doc/keepassxc.md
| 13 | 13 | of keepassxc. It currently implemets most of the configuration, but excludes | |
| 14 | 14 | a few difficult parts. | |
| 15 | 15 | ||
| 16 | - | **Scheme Procedure**: (keepassxc-home config) | |
| 16 | + | **Scheme Variable**: keepassxc-home-type | |
| 17 | 17 | ||
| 18 | - | Generates a configuration file for keepassxc, according to config, a | |
| 19 | - | keepassxc-configuration object. | |
| 18 | + | The type of the service that generates a configuration file for keepassxc. Its | |
| 19 | + | value is a keepassxc-configuration object. | |
| 20 | 20 | ||
| 21 | 21 | **Data Type**: keepassxc-configuration | |
| 22 | 22 | ||
… | |||
| 55 | 55 | ------- | |
| 56 | 56 | ||
| 57 | 57 | ```scheme | |
| 58 | - | (keepassxc-home | |
| 58 | + | (user-home | |
| 59 | + | keepassxc-home-type | |
| 59 | 60 | (keepassxc-configuration | |
| 60 | 61 | (last-databases '("/data/alice/pass.kbdx")) | |
| 61 | 62 | (last-dir "/data/alice") | |
doc/openbox.md
| 8 | 8 | Main Configuration | |
| 9 | 9 | ------------------ | |
| 10 | 10 | ||
| 11 | - | Openbox is configured by using the `openbox-home` procedure. | |
| 11 | + | Openbox is configured by using the `openbox-home-type` service type. | |
| 12 | 12 | ||
| 13 | - | **Scheme Procedure**: (openbox-home config) | |
| 13 | + | **Scheme Procedure**: openbox-home-type | |
| 14 | 14 | ||
| 15 | - | Generates configuration files for openbox, according to config, an | |
| 16 | - | openbox-configuration object. | |
| 15 | + | The type of service that generates configuration files for openbox. Its value | |
| 16 | + | is an openbox-configuration object. | |
| 17 | 17 | ||
| 18 | 18 | **Data Type**: openbox-configuration | |
| 19 | 19 | ||
… | |||
| 34 | 34 | --------------------- | |
| 35 | 35 | ||
| 36 | 36 | ```scheme | |
| 37 | - | (openbox-home | |
| 37 | + | (user-home | |
| 38 | + | openbox-home-type | |
| 38 | 39 | (openbox-configuration | |
| 39 | 40 | (autostart (local-file "files/autostart")) | |
| 40 | 41 | (menus | |
… | |||
| 97 | 98 | * **label**: a label shown in the parent menu that executes this element | |
| 98 | 99 | * **command**: the command to execute when the user clicks on this menu element. | |
| 99 | 100 | It can be a string or a g-expression, as seen in the first example. | |
| 100 | - | * **notify?** (default #t): whether to use startupnotify | |
| 100 | > | ||
| 101 | 0 | > | \ No newline at end of file |
| 101 | + | * **notify?** (default #t): whether to use startupnotify | |
doc/ssh.md
| 8 | 8 | ------------------ | |
| 9 | 9 | ||
| 10 | 10 | The main configuration is not complete compared to the configuration possibilities | |
| 11 | - | of the client. It however implements a big part of the possibilities. | |
| 11 | + | of the client. It however implements a big part of the possibilities. | |
| 12 | 12 | ||
| 13 | - | **Scheme Procedure**: (ssh-home config) | |
| 13 | + | **Scheme Variable**: ssh-home-type | |
| 14 | 14 | ||
| 15 | - | Generates configuration files for OpenSSH, according to config, an | |
| 16 | - | ssh-configuration object. | |
| 15 | + | The type of service that generates configuration files for OpenSSH. Its value | |
| 16 | + | is an ssh-configuration object. | |
| 17 | 17 | ||
| 18 | 18 | **Data Type**: ssh-configuration | |
| 19 | 19 | ||
… | |||
| 36 | 36 | ------- | |
| 37 | 37 | ||
| 38 | 38 | ```scheme | |
| 39 | - | (ssh-home | |
| 39 | + | (user-home | |
| 40 | + | ssh-home-type | |
| 40 | 41 | (ssh-configuration | |
| 41 | 42 | (authorized-keys '("ssh-rsa ... alice@computilo")) | |
| 42 | 43 | (known-hosts | |
home.scm
| 23 | 23 | #:use-module (guix licenses) | |
| 24 | 24 | #:use-module (guix packages) | |
| 25 | 25 | #:use-module (guix records) | |
| 26 | + | #:use-module (guix ui) | |
| 27 | + | #:use-module (guix utils) | |
| 26 | 28 | #:use-module (ice-9 match) | |
| 29 | + | #:use-module (ice-9 vlist) | |
| 27 | 30 | #:use-module (home build utils) | |
| 31 | + | #:use-module (srfi srfi-1) | |
| 32 | + | #:use-module (srfi srfi-9) | |
| 33 | + | #:use-module (srfi srfi-35) | |
| 28 | 34 | #:export (use-home-modules | |
| 29 | 35 | home | |
| 30 | 36 | home? | |
… | |||
| 33 | 39 | home-guix-config-symlink | |
| 34 | 40 | home-local-symlink | |
| 35 | 41 | home-cache-symlink | |
| 36 | - | home->derivation)) | |
| 42 | + | home->derivation | |
| 43 | + | ||
| 44 | + | user-home | |
| 45 | + | user-home-type | |
| 46 | + | user-home-value | |
| 47 | + | ||
| 48 | + | home-type | |
| 49 | + | home-type? | |
| 50 | + | home-type-name | |
| 51 | + | home-type-extensions | |
| 52 | + | home-type-extension-points | |
| 53 | + | home-type-default-value | |
| 54 | + | home-type-description | |
| 55 | + | home-type-location | |
| 56 | + | ||
| 57 | + | home-extension | |
| 58 | + | home-extension? | |
| 59 | + | home-extension-target | |
| 60 | + | home-extension-target-point | |
| 61 | + | home-extension-compute | |
| 62 | + | ||
| 63 | + | home-extension-point | |
| 64 | + | home-extension-point? | |
| 65 | + | home-extension-point-name | |
| 66 | + | home-extension-point-compose | |
| 67 | + | home-extension-point-extend | |
| 68 | + | ||
| 69 | + | root-home-type)) | |
| 70 | + | ||
| 71 | + | ;;; | |
| 72 | + | ;;; Service-like home configuration mechanism | |
| 73 | + | ;;; | |
| 74 | + | ||
| 75 | + | (define &no-default-value | |
| 76 | + | '(no default value)) | |
| 77 | + | ||
| 78 | + | (define-record-type* <home-extension> home-extension make-home-extension | |
| 79 | + | home-extension? | |
| 80 | + | (target home-extension-target ; home-type | |
| 81 | + | (default #f)) | |
| 82 | + | (point home-extension-target-point ; symbol | |
| 83 | + | (default #f)) | |
| 84 | + | ;; A function that takes the user-home value as parameter and returns the | |
| 85 | + | ;; value to be passed to the extension point. | |
| 86 | + | (compute home-extension-compute)) | |
| 87 | + | ||
| 88 | + | (define-record-type* <home-extension-point> home-extension-point | |
| 89 | + | make-home-extension-point home-extension-point? | |
| 90 | + | (name home-extension-point-name ; symbol | |
| 91 | + | (default #f)) | |
| 92 | + | ;; A function that composes extensions. It is passed a list of extension values | |
| 93 | + | ;; and returns one extension value | |
| 94 | + | (compose home-extension-point-compose) | |
| 95 | + | ;; A function that extends the original service value with the result of | |
| 96 | + | ;; the composition. It is passed two arguments: the user-home value and the | |
| 97 | + | ;; result of the composition. It returns a new user-home value. | |
| 98 | + | (extend home-extension-point-extend)) ; any(value) -> any(compose) -> any(value) | |
| 99 | + | ||
| 100 | + | (define-record-type* <home-type> home-type make-home-type | |
| 101 | + | home-type? | |
| 102 | + | (name home-type-name) ; symbol | |
| 103 | + | (extensions home-type-extensions ; list home-extension | |
| 104 | + | (default #f)) | |
| 105 | + | (extension-points home-type-extension-points ; list home-extension-point | |
| 106 | + | (default #f)) | |
| 107 | + | (default-value home-type-default-value ; any | |
| 108 | + | (default &no-default-value)) | |
| 109 | + | (description home-type-description ; string | |
| 110 | + | (default #f)) | |
| 111 | + | (location home-type-location | |
| 112 | + | (default (and=> (current-source-location) | |
| 113 | + | source-properties->location)) | |
| 114 | + | (innate))) | |
| 115 | + | ||
| 116 | + | (define-record-type <user-home> | |
| 117 | + | (make-user-home type value) | |
| 118 | + | user-home? | |
| 119 | + | (type user-home-type) | |
| 120 | + | (value user-home-value)) | |
| 121 | + | ||
| 122 | + | (define-syntax user-home | |
| 123 | + | (syntax-rules () | |
| 124 | + | "Return a user-home instance of TYPE. The user-home value is VALUE or, if | |
| 125 | + | omitted, TYPE's default value." | |
| 126 | + | ((_ type value) | |
| 127 | + | (make-user-home type value)) | |
| 128 | + | ((_ type) | |
| 129 | + | (%user-home-with-default-value (current-source-location) | |
| 130 | + | type)))) | |
| 131 | + | ||
| 132 | + | (define (%user-home-with-default-value location type) | |
| 133 | + | "Return an instance of user-home type TYPE with its default value, if any. If | |
| 134 | + | TYPE does not have a default value, an error is raised." | |
| 135 | + | ;; TODO: Currently this is a run-time error but with a little bit macrology | |
| 136 | + | ;; we could turn it into an expansion-time error. | |
| 137 | + | (let ((default (home-type-default-value type))) | |
| 138 | + | (if (eq? default &no-default-value) | |
| 139 | + | (let ((location (source-properties->location location))) | |
| 140 | + | (raise | |
| 141 | + | (condition | |
| 142 | + | (&missing-value-home-error (type type) (location location)) | |
| 143 | + | (&message | |
| 144 | + | (message (format #f (G_ "~a: no value specified \ | |
| 145 | + | for home configuration of type '~a'") | |
| 146 | + | (location->string location) | |
| 147 | + | (home-type-name type))))))) | |
| 148 | + | (user-home type default)))) | |
| 149 | + | ||
| 150 | + | (define-condition-type &home-error &error | |
| 151 | + | home-error?) | |
| 152 | + | ||
| 153 | + | (define-condition-type &missing-value-home-error &home-error | |
| 154 | + | missing-value-home-error? | |
| 155 | + | (type missing-value-home-error-type) | |
| 156 | + | (location missing-value-home-error-location)) | |
| 157 | + | ||
| 158 | + | (define-condition-type &missing-target-home-error &home-error | |
| 159 | + | missing-target-home-error? | |
| 160 | + | (home missing-target-home-error-home) | |
| 161 | + | (target-type missing-target-home-error-target-type)) | |
| 162 | + | ||
| 163 | + | (define-condition-type &ambiguous-target-home-error &home-error | |
| 164 | + | ambiguous-target-home-error? | |
| 165 | + | (home missing-target-home-error-home) | |
| 166 | + | (target-type missing-target-home-error-target-type)) | |
| 167 | + | ||
| 168 | + | (define root-home-type | |
| 169 | + | (home-type | |
| 170 | + | (name 'root) | |
| 171 | + | (extension-points | |
| 172 | + | (list (home-extension-point | |
| 173 | + | (compose (lambda (l) (apply append l))) | |
| 174 | + | (extend (lambda (v l) (apply append v l)))))) | |
| 175 | + | (default-value '()) | |
| 176 | + | (description "The root home type"))) | |
| 177 | + | ||
| 178 | + | ;;; | |
| 179 | + | ;;; Home composition | |
| 180 | + | ;;; | |
| 181 | + | ||
| 182 | + | (define (missing-target-error home target-type) | |
| 183 | + | (raise | |
| 184 | + | (condition (&missing-target-home-error | |
| 185 | + | (home home) | |
| 186 | + | (target-type target-type)) | |
| 187 | + | (&message | |
| 188 | + | (message | |
| 189 | + | (format #f (G_ "no target of type '~a' for home configuration '~a'") | |
| 190 | + | (home-type-name target-type) | |
| 191 | + | (home-type-name | |
| 192 | + | (user-home-type home)))))))) | |
| 193 | + | ||
| 194 | + | (define (home-back-edges homes) | |
| 195 | + | "Return a procedure which, when passed a user-home from HOMES, returns the | |
| 196 | + | list of <user-home> that extend it." | |
| 197 | + | (define (add-edges home edges) | |
| 198 | + | (define (add-edge extension edges) | |
| 199 | + | (define (add-extension-edge target edges) | |
| 200 | + | (vhash-consq target home edges)) | |
| 201 | + | (let ((target-type (home-extension-target extension)) | |
| 202 | + | (target-point (home-extension-target-point extension))) | |
| 203 | + | (match (filter | |
| 204 | + | (lambda (home) | |
| 205 | + | (if target-type | |
| 206 | + | (eq? (user-home-type home) target-type) | |
| 207 | + | (and target-point | |
| 208 | + | (not (null? (filter | |
| 209 | + | (lambda (extension-point) | |
| 210 | + | (eq? | |
| 211 | + | (home-extension-point-name extension-point) | |
| 212 | + | target-point)) | |
| 213 | + | (home-type-extension-points | |
| 214 | + | (user-home-type home)))))))) | |
| 215 | + | homes) | |
| 216 | + | ((target ...) | |
| 217 | + | (fold add-extension-edge edges target)) | |
| 218 | + | (() | |
| 219 | + | (missing-target-error home target-type))))) | |
| 220 | + | (let ((extensions (home-type-extensions (user-home-type home)))) | |
| 221 | + | (if extensions | |
| 222 | + | (fold add-edge edges (home-type-extensions (user-home-type home))) | |
| 223 | + | edges))) | |
| 224 | + | ||
| 225 | + | (let ((edges (fold add-edges vlist-null homes))) | |
| 226 | + | (lambda (node) | |
| 227 | + | (reverse (vhash-foldq* cons '() node edges))))) | |
| 228 | + | ||
| 229 | + | (define (instantiate-missing-user-homes homes) | |
| 230 | + | "Return HOMES, a list of user-home, augmented with any user-home targeted by | |
| 231 | + | extensions and missing from HOMES. Only home types with a default value can | |
| 232 | + | be instantiated; other missing user-homes lead to a '&missing-target-home-error'." | |
| 233 | + | (let loop ((homes homes)) | |
| 234 | + | (define (not-present? target) | |
| 235 | + | (let ((target-type (home-extension-target target))) | |
| 236 | + | (and target-type | |
| 237 | + | (null? (filter (lambda (home) | |
| 238 | + | (eq? (user-home-type home) target-type)) | |
| 239 | + | homes))))) | |
| 240 | + | (define additions | |
| 241 | + | (append-map | |
| 242 | + | (lambda (home) | |
| 243 | + | (let ((extensions (home-type-extensions (user-home-type home)))) | |
| 244 | + | (if extensions | |
| 245 | + | (map (lambda (extension) (home-extension-target extension)) | |
| 246 | + | (filter not-present? extensions)) | |
| 247 | + | '()))) | |
| 248 | + | homes)) | |
| 249 | + | ||
| 250 | + | (define (uniq lst) | |
| 251 | + | (let loop ((types lst) (result '())) | |
| 252 | + | (match types | |
| 253 | + | ((type types ...) | |
| 254 | + | (if (member type types) | |
| 255 | + | (loop types result) | |
| 256 | + | (loop types (cons type result)))) | |
| 257 | + | (() result)))) | |
| 258 | + | ||
| 259 | + | (define generated | |
| 260 | + | (map | |
| 261 | + | (lambda (type) | |
| 262 | + | (let ((default (home-type-default-value type))) | |
| 263 | + | (if (eq? default &no-default-value) | |
| 264 | + | (missing-target-error home target-type) | |
| 265 | + | (user-home type default)))) | |
| 266 | + | (uniq additions))) | |
| 267 | + | ||
| 268 | + | (if (null? generated) | |
| 269 | + | homes | |
| 270 | + | (loop (append homes generated))))) | |
| 271 | + | ||
| 272 | + | (define (fold-home target-type homes) | |
| 273 | + | "fold HOMES by successively resolving extension points, until we get only | |
| 274 | + | one user-home of type TARGET-TYPE." | |
| 275 | + | (define dependents | |
| 276 | + | (home-back-edges homes)) | |
| 277 | + | ||
| 278 | + | (define (apply-extension target) | |
| 279 | + | (define (update-extension extensions point home) | |
| 280 | + | (let* ((point-name (home-extension-point-name point)) | |
| 281 | + | (matched-extensions | |
| 282 | + | (filter (lambda (extension) | |
| 283 | + | (if point-name | |
| 284 | + | (eq? (home-extension-target-point extension) | |
| 285 | + | point-name) | |
| 286 | + | (eq? (home-extension-target extension) | |
| 287 | + | (user-home-type target)))) | |
| 288 | + | (home-type-extensions (user-home-type home))))) | |
| 289 | + | (if (null? matched-extensions) | |
| 290 | + | extensions | |
| 291 | + | (append | |
| 292 | + | (map | |
| 293 | + | (lambda (extension) | |
| 294 | + | `(,point-name ,((home-extension-compute extension) | |
| 295 | + | (user-home-value home)))) | |
| 296 | + | matched-extensions) | |
| 297 | + | extensions)))) | |
| 298 | + | (lambda (home) | |
| 299 | + | (let loop ((extensions '()) (points (home-type-extension-points | |
| 300 | + | (user-home-type target)))) | |
| 301 | + | (match points | |
| 302 | + | (() extensions) | |
| 303 | + | ((point points ...) | |
| 304 | + | (loop | |
| 305 | + | (update-extension extensions point home) | |
| 306 | + | points)))))) | |
| 307 | + | ||
| 308 | + | (define (merge-extensions points extensions) | |
| 309 | + | (let loop ((points points) (extensions extensions)) | |
| 310 | + | (match points | |
| 311 | + | (() extensions) | |
| 312 | + | (((point value) points ...) | |
| 313 | + | (loop points (acons point | |
| 314 | + | (let ((v (assoc-ref extensions point))) | |
| 315 | + | (if v (cons value v) (list value))) | |
| 316 | + | extensions)))))) | |
| 317 | + | ||
| 318 | + | (define (compose-extension target) | |
| 319 | + | (lambda (extension) | |
| 320 | + | (match extension | |
| 321 | + | ((point-name values ...) | |
| 322 | + | (match (filter | |
| 323 | + | (lambda (extension-point) | |
| 324 | + | (eq? (home-extension-point-name extension-point) point-name)) | |
| 325 | + | (home-type-extension-points (user-home-type target))) | |
| 326 | + | ((point) | |
| 327 | + | (list | |
| 328 | + | point-name | |
| 329 | + | ((home-extension-point-compose point) | |
| 330 | + | values)))))))) | |
| 331 | + | ||
| 332 | + | (match (filter (lambda (home) | |
| 333 | + | (eq? (user-home-type home) target-type)) | |
| 334 | + | homes) | |
| 335 | + | ((sink) | |
| 336 | + | (let loop ((sink sink)) | |
| 337 | + | (let* ((dependents (map loop (dependents sink))) | |
| 338 | + | (extensions (map (apply-extension sink) dependents)) | |
| 339 | + | (extensions (fold merge-extensions '() extensions)) | |
| 340 | + | (extensions (map (compose-extension sink) extensions))) | |
| 341 | + | (user-home | |
| 342 | + | (user-home-type sink) | |
| 343 | + | (let ((extension-points (home-type-extension-points (user-home-type sink)))) | |
| 344 | + | (if extension-points | |
| 345 | + | (fold (lambda (extension-point value) | |
| 346 | + | (let* ((extend (home-extension-point-extend extension-point)) | |
| 347 | + | (name (home-extension-point-name extension-point)) | |
| 348 | + | (extension-value (assoc-ref extensions name))) | |
| 349 | + | (if extension-value | |
| 350 | + | (extend value extension-value) | |
| 351 | + | value))) | |
| 352 | + | (user-home-value sink) | |
| 353 | + | (home-type-extension-points (user-home-type sink))) | |
| 354 | + | (user-home-value sink))))))) | |
| 355 | + | (() | |
| 356 | + | (raise | |
| 357 | + | (condition (&missing-target-home-error | |
| 358 | + | (home #f) | |
| 359 | + | (target-type target-type)) | |
| 360 | + | (&message | |
| 361 | + | (message (format #f (G_ "home configuration of type '~a' not found") | |
| 362 | + | (home-type-name target-type))))))) | |
| 363 | + | (x | |
| 364 | + | (raise | |
| 365 | + | (condition (&ambiguous-target-home-error | |
| 366 | + | (home #f) | |
| 367 | + | (target-type target-type)) | |
| 368 | + | (&message | |
| 369 | + | (message (format #f (G_ "home configuration of type '~a' not found") | |
| 370 | + | (home-type-name target-type))))))))) | |
| 371 | + | ||
| 372 | + | ;;; | |
| 373 | + | ;;; Home generation | |
| 374 | + | ;;; | |
| 37 | 375 | ||
| 38 | 376 | (define-syntax use-home-modules | |
| 39 | 377 | (syntax-rules () | |
… | |||
| 44 | 382 | make-home | |
| 45 | 383 | home? | |
| 46 | 384 | (data-directory home-data-directory) | |
| 47 | - | (guix-symlink home-guix-symlink (thunked) | |
| 48 | - | (default (string-append | |
| 49 | - | (home-data-directory this-record) | |
| 50 | - | "/.guix-profile"))) | |
| 51 | - | (guix-config-symlink home-guix-config-symlink (thunked) | |
| 52 | - | (default (string-append | |
| 53 | - | (home-data-directory this-record) | |
| 54 | - | "/.config/guix"))) | |
| 55 | - | (local-symlink home-local-symlink (thunked) | |
| 56 | - | (default (string-append | |
| 57 | - | (home-data-directory this-record) | |
| 58 | - | "/.local"))) | |
| 59 | - | (cache-symlink home-cache-symlink (thunked) | |
| 60 | - | (default (string-append | |
| 61 | - | (home-data-directory this-record) | |
| 62 | - | "/.cache"))) | |
| 385 | + | (base-configuration home-base-configuration (thunked) | |
| 386 | + | (default | |
| 387 | + | (base-home-configuration | |
| 388 | + | (guix-symlink | |
| 389 | + | (string-append (home-data-directory this-record) "/.guix-profile")) | |
| 390 | + | (guix-config-symlink | |
| 391 | + | (string-append (home-data-directory this-record) "/.config/guix")) | |
| 392 | + | (local-symlink | |
| 393 | + | (string-append (home-data-directory this-record) "/.local")) | |
| 394 | + | (cache-symlink | |
| 395 | + | (string-append (home-data-directory this-record) "/.cache"))))) | |
| 63 | 396 | (configurations home-configurations | |
| 64 | - | (default '()))) | |
| 397 | + | (default (list (user-home root-home-type))))) | |
| 398 | + | ||
| 399 | + | (define-record-type* <base-home-configuration> base-home-configuration | |
| 400 | + | make-base-home-configuration | |
| 401 | + | base-home-configuration? | |
| 402 | + | (guix-symlink base-home-configuration-guix-symlink) | |
| 403 | + | (guix-config-symlink base-home-configuration-guix-config-symlink) | |
| 404 | + | (local-symlink base-home-configuration-local-symlink) | |
| 405 | + | (cache-symlink base-home-configuration-cache-symlink)) | |
| 406 | + | ||
| 407 | + | (define base-home-type | |
| 408 | + | (home-type | |
| 409 | + | (name 'guix) | |
| 410 | + | (extensions | |
| 411 | + | (list | |
| 412 | + | (home-extension | |
| 413 | + | (target root-home-type) | |
| 414 | + | (compute (lambda (config) | |
| 415 | + | `((".guix-profile" | |
| 416 | + | ,(base-home-configuration-guix-symlink config)) | |
| 417 | + | (".config/guix" | |
| 418 | + | ,(base-home-configuration-guix-config-symlink config)) | |
| 419 | + | (".local" | |
| 420 | + | ,(base-home-configuration-local-symlink config)) | |
| 421 | + | (".cache" | |
| 422 | + | ,(base-home-configuration-cache-symlink config)))))))))) | |
| 65 | 423 | ||
| 66 | 424 | (define (home->derivation home) | |
| 67 | 425 | (define builder | |
| 68 | 426 | (with-imported-modules | |
| 69 | - | '((guix build utils) (home build utils)) | |
| 427 | + | '((guix build utils) (home build utils) (ice-9 match)) | |
| 70 | 428 | #~(begin | |
| 71 | - | (use-modules (guix build utils) (home build utils)) | |
| 72 | - | (mkdir-p (home-file #$output ".config")) | |
| 73 | - | ;; For guix | |
| 74 | - | (symlink #$(home-guix-config-symlink home) (home-file #$output ".config/guix")) | |
| 75 | - | (symlink #$(home-guix-symlink home) (home-file #$output ".guix-profile")) | |
| 76 | - | ;; symlink writeable directories | |
| 77 | - | (symlink #$(home-local-symlink home) (home-file #$output ".local")) | |
| 78 | - | (symlink #$(home-cache-symlink home) (home-file #$output ".cache")) | |
| 79 | - | ;; rest of the files | |
| 80 | - | (for-each | |
| 81 | - | (lambda (config) | |
| 82 | - | (with-directory-excursion config | |
| 83 | - | (for-each | |
| 84 | - | (lambda (f) | |
| 85 | - | (mkdir-p (home-file #$output (dirname f))) | |
| 86 | - | (symlink (home-file config f) | |
| 87 | - | (home-file #$output f))) | |
| 88 | - | (find-files "." ".")))) | |
| 89 | - | (list #$@(home-configurations home)))))) | |
| 429 | + | (use-modules (guix build utils) (home build utils) (ice-9 match)) | |
| 430 | + | #$(let* ((homes (instantiate-missing-user-homes | |
| 431 | + | (cons | |
| 432 | + | (user-home base-home-type (home-base-configuration home)) | |
| 433 | + | (home-configurations home)))) | |
| 434 | + | (root (fold-home root-home-type homes)) | |
| 435 | + | (configs (user-home-value root))) | |
| 436 | + | #~(for-each | |
| 437 | + | (lambda (config) | |
| 438 | + | (match config | |
| 439 | + | ((home-name target) | |
| 440 | + | (mkdir-p (dirname (home-file #$output home-name))) | |
| 441 | + | (symlink target (home-file #$output home-name))))) | |
| 442 | + | '(#$@configs)))))) | |
| 90 | 443 | (gexp->derivation "home" builder | |
| 91 | 444 | #:substitutable? #f | |
| 92 | 445 | #:local-build? #t)) | |
home/hexchat.scm
| 21 | 21 | #:use-module (guix records) | |
| 22 | 22 | #:use-module (gnu packages lxde) | |
| 23 | 23 | #:use-module (ice-9 match) | |
| 24 | + | #:use-module (home) | |
| 24 | 25 | #:export (hexchat-configuration | |
| 25 | 26 | hexchat-configuration-servlist | |
| 26 | 27 | hexchat-configuration-log-dir | |
… | |||
| 34 | 35 | hexchat-server-servers | |
| 35 | 36 | hexchat-server-flags | |
| 36 | 37 | ||
| 37 | - | hexchat-home)) | |
| 38 | + | hexchat-home-type)) | |
| 38 | 39 | ||
| 39 | 40 | (define-record-type* <hexchat-server> | |
| 40 | 41 | hexchat-server make-hexchat-server | |
… | |||
| 100 | 101 | (log-dir hexchat-configuration-log-dir) | |
| 101 | 102 | (scrollback-dir hexchat-configuraton-scrollback-dir)) | |
| 102 | 103 | ||
| 103 | - | (define (hexchat-home config) | |
| 104 | - | (computed-file "hexchat-home" | |
| 105 | - | (match config | |
| 106 | - | (($ <hexchat-configuration> servlist log-dir scrollback-dir) | |
| 107 | - | #~(let ((servlist.conf #$(plain-file "servlist.conf" (generate-hexchat-servlist servlist))) | |
| 108 | - | (hexchat-dir (string-append #$output "/.config/hexchat"))) | |
| 109 | - | (use-modules (guix build utils)) | |
| 110 | - | (mkdir-p hexchat-dir) | |
| 111 | - | (symlink #$log-dir (string-append hexchat-dir "/logs")) | |
| 112 | - | (symlink #$scrollback-dir (string-append hexchat-dir "/scrollback")) | |
| 113 | - | (copy-file servlist.conf (string-append hexchat-dir "/servlist.conf"))))) | |
| 114 | - | #:options | |
| 115 | - | '(#:local-build? #t | |
| 116 | - | #:modules ((guix build utils))))) | |
| 116 | > | ||
| 117 | 0 | > | \ No newline at end of file |
| 104 | + | (define hexchat-home-type | |
| 105 | + | (home-type | |
| 106 | + | (name 'hexchat) | |
| 107 | + | (extensions | |
| 108 | + | (list | |
| 109 | + | (home-extension | |
| 110 | + | (target root-home-type) | |
| 111 | + | (compute | |
| 112 | + | (lambda (config) | |
| 113 | + | (match config | |
| 114 | + | (($ <hexchat-configuration> servlist log-dir scrollback-dir) | |
| 115 | + | (let ((servlist.conf (plain-file "servlist.conf" (generate-hexchat-servlist servlist)))) | |
| 116 | + | `((".config/hexchat/servlist.conf" ,servlist.conf) | |
| 117 | + | (".config/hexchat/logs" ,log-dir) | |
| 118 | + | (".config/hexchat/scrollback" ,scrollback-dir)))))))))))) | |
home/keepassxc.scm
| 22 | 22 | #:use-module (gnu packages lxde) | |
| 23 | 23 | #:use-module (ice-9 match) | |
| 24 | 24 | #:use-module (home utils) | |
| 25 | + | #:use-module (home) | |
| 25 | 26 | #:export (keepassxc-configuration | |
| 26 | 27 | keepassxc-last-databases | |
| 27 | 28 | keepassxc-last-dir | |
… | |||
| 42 | 43 | keepassxc-wordlist | |
| 43 | 44 | keepassxc-word-separator | |
| 44 | 45 | ||
| 45 | - | keepassxc-home)) | |
| 46 | + | keepassxc-home-type)) | |
| 46 | 47 | ||
| 47 | 48 | (define-record-type* <keepassxc-configuration> | |
| 48 | 49 | keepassxc-configuration make-keepassxc-configuration | |
… | |||
| 84 | 85 | (word-separator keepassxc-word-separator | |
| 85 | 86 | (default " "))) | |
| 86 | 87 | ||
| 87 | - | (define (keepassxc-home config) | |
| 88 | - | (computed-file "keepassxc-home" | |
| 89 | - | (let ((keepassxc.ini (make-ini-file "keepassxc.ini" | |
| 90 | - | `(("General" | |
| 91 | - | (("LastDatabases" | |
| 92 | - | ,(string-join | |
| 93 | - | (keepassxc-last-databases config) | |
| 94 | - | ", ")) | |
| 95 | - | ("LastDir" | |
| 96 | - | ,(or (keepassxc-last-dir config) "")) | |
| 97 | - | ("LastOpenedDatabases" | |
| 98 | - | ,(string-join | |
| 99 | - | (keepassxc-last-opened-databases config) | |
| 100 | - | ", ")))) | |
| 101 | - | ("GUI" | |
| 102 | - | (("HidePasswords" | |
| 103 | - | ,(keepassxc-hide-passwords? config)) | |
| 104 | - | ("HideUsernames" | |
| 105 | - | ,(keepassxc-hide-usernames? config)))) | |
| 106 | - | ("generator" | |
| 107 | - | (("EASCII" | |
| 108 | - | ,(keepassxc-use-eascii? config)) | |
| 109 | - | ("EnsureEvery" | |
| 110 | - | ,(keepassxc-ensure-every? config)) | |
| 111 | - | ("ExcludeAlike" | |
| 112 | - | ,(keepassxc-exclude-alike? config)) | |
| 113 | - | ("Length" | |
| 114 | - | ,(keepassxc-password-length config)) | |
| 115 | - | ("LowerCase" | |
| 116 | - | ,(keepassxc-use-lower-case? config)) | |
| 117 | - | ("Numbers" | |
| 118 | - | ,(keepassxc-use-numbers? config)) | |
| 119 | - | ("SpecialChars" | |
| 120 | - | ,(keepassxc-use-special-chars? config)) | |
| 121 | - | ("Type" | |
| 122 | - | ,(keepassxc-type config)) | |
| 123 | - | ("UpperCase" | |
| 124 | - | ,(keepassxc-use-upper-case? config)) | |
| 125 | - | ("WordCount" | |
| 126 | - | ,(keepassxc-word-count config)) | |
| 127 | - | ("WordList" | |
| 128 | - | ,(keepassxc-wordlist config)) | |
| 129 | - | ("WordSeparator" | |
| 130 | - | ,(keepassxc-word-separator config)))))))) | |
| 131 | - | #~(begin | |
| 132 | - | (let ((keepassxc-dir (string-append #$output "/.config/keepassxc"))) | |
| 133 | - | (use-modules (guix build utils)) | |
| 134 | - | (mkdir-p keepassxc-dir) | |
| 135 | - | (copy-file #$keepassxc.ini (string-append keepassxc-dir "/keepassxc.ini"))))) | |
| 136 | - | #:options | |
| 137 | - | '(#:local-build? #t | |
| 138 | - | #:modules ((guix build utils))))) | |
| 88 | + | (define keepassxc-home-type | |
| 89 | + | (home-type | |
| 90 | + | (name 'keepassxc) | |
| 91 | + | (extensions | |
| 92 | + | (list | |
| 93 | + | (home-extension | |
| 94 | + | (target root-home-type) | |
| 95 | + | (compute (lambda (config) | |
| 96 | + | (let ((keepassxc.ini | |
| 97 | + | (make-ini-file "keepassxc.ini" | |
| 98 | + | `(("General" | |
| 99 | + | (("LastDatabases" | |
| 100 | + | ,(string-join | |
| 101 | + | (keepassxc-last-databases config) | |
| 102 | + | ", ")) | |
| 103 | + | ("LastDir" | |
| 104 | + | ,(or (keepassxc-last-dir config) "")) | |
| 105 | + | ("LastOpenedDatabases" | |
| 106 | + | ,(string-join | |
| 107 | + | (keepassxc-last-opened-databases config) | |
| 108 | + | ", ")))) | |
| 109 | + | ("GUI" | |
| 110 | + | (("HidePasswords" | |
| 111 | + | ,(keepassxc-hide-passwords? config)) | |
| 112 | + | ("HideUsernames" | |
| 113 | + | ,(keepassxc-hide-usernames? config)))) | |
| 114 | + | ("generator" | |
| 115 | + | (("EASCII" | |
| 116 | + | ,(keepassxc-use-eascii? config)) | |
| 117 | + | ("EnsureEvery" | |
| 118 | + | ,(keepassxc-ensure-every? config)) | |
| 119 | + | ("ExcludeAlike" | |
| 120 | + | ,(keepassxc-exclude-alike? config)) | |
| 121 | + | ("Length" | |
| 122 | + | ,(keepassxc-password-length config)) | |
| 123 | + | ("LowerCase" | |
| 124 | + | ,(keepassxc-use-lower-case? config)) | |
| 125 | + | ("Numbers" | |
| 126 | + | ,(keepassxc-use-numbers? config)) | |
| 127 | + | ("SpecialChars" | |
| 128 | + | ,(keepassxc-use-special-chars? config)) | |
| 129 | + | ("Type" | |
| 130 | + | ,(keepassxc-type config)) | |
| 131 | + | ("UpperCase" | |
| 132 | + | ,(keepassxc-use-upper-case? config)) | |
| 133 | + | ("WordCount" | |
| 134 | + | ,(keepassxc-word-count config)) | |
| 135 | + | ("WordList" | |
| 136 | + | ,(keepassxc-wordlist config)) | |
| 137 | + | ("WordSeparator" | |
| 138 | + | ,(keepassxc-word-separator config)))))))) | |
| 139 | + | `((".config/keepassxc/keepassxc.ini" ,keepassxc.ini)))))))))) | |
home/openbox.scm
| 23 | 23 | #:use-module (guix packages) | |
| 24 | 24 | #:use-module (guix records) | |
| 25 | 25 | #:use-module (gnu packages lxde) | |
| 26 | + | #:use-module (home) | |
| 26 | 27 | #:use-module (ice-9 match) | |
| 27 | 28 | #:export (openbox-configuration | |
| 28 | 29 | openbox-configuration? | |
… | |||
| 39 | 40 | openbox-element-menu | |
| 40 | 41 | openbox-element-execute | |
| 41 | 42 | ||
| 42 | - | openbox-home)) | |
| 43 | + | openbox-home-type)) | |
| 43 | 44 | ||
| 44 | 45 | (define-record-type* <openbox-configuration> | |
| 45 | 46 | openbox-configuration make-openbox-configuration | |
… | |||
| 114 | 115 | (#f (plain-file "rc.xml" "")) | |
| 115 | 116 | (_ rc))) | |
| 116 | 117 | ||
| 117 | - | (define (openbox-home config) | |
| 118 | - | (computed-file "openbox-home" | |
| 119 | - | (match config | |
| 120 | - | (($ <openbox-configuration> autostart environ menus root-elements rc) | |
| 121 | - | #~(let ((menu.xml #$(computed-file "menu.xml" (generate-openbox-menu menus root-elements))) | |
| 122 | - | (autostart #$(openbox-autostart autostart)) | |
| 123 | - | (environ #$(openbox-environment environ)) | |
| 124 | - | (rc #$(openbox-rc rc)) | |
| 125 | - | (openbox-dir (string-append #$output "/.config/openbox"))) | |
| 126 | - | (use-modules (guix build utils)) | |
| 127 | - | (mkdir-p openbox-dir) | |
| 128 | - | (copy-file autostart (string-append openbox-dir "/autostart")) | |
| 129 | - | (copy-file environ (string-append openbox-dir "/environment")) | |
| 130 | - | (copy-file menu.xml (string-append openbox-dir "/menu.xml")) | |
| 131 | - | (copy-file rc (string-append openbox-dir "/rc.xml"))))) | |
| 132 | - | #:options | |
| 133 | - | '(#:local-build? #t | |
| 134 | - | #:modules ((guix build utils))))) | |
| 134 | > | ||
| 135 | 0 | > | \ No newline at end of file |
| 118 | + | (define openbox-home-type | |
| 119 | + | (home-type | |
| 120 | + | (name 'openbox) | |
| 121 | + | (default-value (openbox-configuration)) | |
| 122 | + | (extensions | |
| 123 | + | (list | |
| 124 | + | (home-extension | |
| 125 | + | (target root-home-type) | |
| 126 | + | (compute | |
| 127 | + | (lambda (config) | |
| 128 | + | (match config | |
| 129 | + | (($ <openbox-configuration> autostart environ menus root-elements rc) | |
| 130 | + | `((".config/openbox/menu.xml" | |
| 131 | + | ,(computed-file "menu.xml" (generate-openbox-menu menus root-elements))) | |
| 132 | + | (".config/openbox/autostart" ,(openbox-autostart autostart)) | |
| 133 | + | (".config/openbox/environment" ,(openbox-environment environ)) | |
| 134 | + | (".config/openbox/rc.xml" ,(openbox-rc rc)))))))))))) | |
home/ssh.scm
| 21 | 21 | #:use-module (guix records) | |
| 22 | 22 | #:use-module (gnu packages lxde) | |
| 23 | 23 | #:use-module (ice-9 match) | |
| 24 | + | #:use-module (home) | |
| 24 | 25 | #:export (ssh-configuration | |
| 25 | 26 | ssh-configuration-authorized-keys | |
| 26 | 27 | ssh-configuration-known-hosts | |
… | |||
| 39 | 40 | ssh-known-host-configuration-algo | |
| 40 | 41 | ssh-known-host-configuration-key | |
| 41 | 42 | ||
| 42 | - | ssh-home)) | |
| 43 | + | ssh-home-type)) | |
| 43 | 44 | ||
| 44 | 45 | (define-record-type* <ssh-host-configuration> | |
| 45 | 46 | ssh-host-configuration make-ssh-host-configuration | |
… | |||
| 129 | 130 | (define (generate-ssh-known-hosts lst) | |
| 130 | 131 | (string-join (map known-host lst) "\n")) | |
| 131 | 132 | ||
| 132 | - | (define (ssh-home config) | |
| 133 | - | (computed-file "ssh-home" | |
| 134 | - | (match config | |
| 135 | - | (($ <ssh-configuration> authorized-keys known-hosts hosts default-host) | |
| 136 | - | #~(let ((config #$(plain-file "config" (generate-ssh-config hosts default-host))) | |
| 137 | - | (known-hosts #$(plain-file "known_hosts" | |
| 138 | - | (generate-ssh-known-hosts known-hosts))) | |
| 139 | - | (authorized-keys #$(plain-file | |
| 140 | - | "authorized_keys" | |
| 141 | - | (generate-ssh-authorized-keys authorized-keys))) | |
| 142 | - | (ssh-dir (string-append #$output "/.ssh"))) | |
| 143 | - | (use-modules (guix build utils)) | |
| 144 | - | (mkdir-p ssh-dir) | |
| 145 | - | (copy-file authorized-keys (string-append ssh-dir "/authorized_keys")) | |
| 146 | - | (copy-file known-hosts (string-append ssh-dir "/known_hosts")) | |
| 147 | - | (copy-file config (string-append ssh-dir "/config"))))) | |
| 148 | - | #:options | |
| 149 | - | '(#:local-build? #t | |
| 150 | - | #:modules ((guix build utils))))) | |
| 133 | + | (define ssh-home-type | |
| 134 | + | (home-type | |
| 135 | + | (name 'ssh) | |
| 136 | + | (extensions | |
| 137 | + | (list | |
| 138 | + | (home-extension | |
| 139 | + | (target root-home-type) | |
| 140 | + | (compute (lambda (config) | |
| 141 | + | (match config | |
| 142 | + | (($ <ssh-configuration> authorized-keys known-hosts hosts default-host) | |
| 143 | + | (let ((config (plain-file "config" (generate-ssh-config hosts default-host))) | |
| 144 | + | (known-hosts (plain-file "known_hosts" | |
| 145 | + | (generate-ssh-known-hosts known-hosts))) | |
| 146 | + | (authorized-keys (plain-file "authorized_keys" | |
| 147 | + | (generate-ssh-authorized-keys authorized-keys)))) | |
| 148 | + | `((".ssh/authorized_keys" ,authorized-keys) (".ssh/known_hosts" ,known-hosts) | |
| 149 | + | (".ssh/config" ,config)))))))))))) | |
home/utils.scm
| 19 | 19 | #:use-module (guix build utils) | |
| 20 | 20 | #:use-module (guix gexp) | |
| 21 | 21 | #:use-module (ice-9 match) | |
| 22 | + | #:use-module (home) | |
| 22 | 23 | #:export (simple-file-home | |
| 23 | 24 | symlink-file-home | |
| 24 | 25 | make-ini-file)) | |
| 25 | 26 | ||
| 26 | 27 | (define (simple-file-home file-gexp location) | |
| 27 | - | "Add @var{file-gexp}, a file-like object, to the user home at @var{location}." | |
| 28 | - | (computed-file "simple-file-home" | |
| 29 | - | #~(begin | |
| 30 | - | (use-modules (guix build utils)) | |
| 31 | - | (mkdir-p (string-append #$output "/" #$(dirname location))) | |
| 32 | - | (copy-file #$file-gexp (string-append #$output "/" #$location))) | |
| 33 | - | #:options | |
| 34 | - | '(#:local-build? #t | |
| 35 | - | #:modules ((guix build utils))))) | |
| 28 | + | (user-home | |
| 29 | + | (home-type | |
| 30 | + | (name 'simple-file) | |
| 31 | + | (extensions | |
| 32 | + | (list | |
| 33 | + | (home-extension | |
| 34 | + | (target root-home-type) | |
| 35 | + | (compute | |
| 36 | + | (const `((,location ,file-gexp)))))))) | |
| 37 | + | #t)) | |
| 36 | 38 | ||
| 37 | - | (define (symlink-file-home from to) | |
| 39 | + | (define (symlink-file-home to from) | |
| 38 | 40 | "Create a symlink from the user home at @var{from} that points to @var{to}." | |
| 39 | - | (computed-file "symlink-file-home" | |
| 40 | - | #~(begin | |
| 41 | - | (use-modules (guix build utils)) | |
| 42 | - | (mkdir-p (string-append #$output "/" #$(dirname to))) | |
| 43 | - | (symlink #$from (string-append #$output "/" #$to))) | |
| 44 | - | #:options | |
| 45 | - | '(#:local-build? #t | |
| 46 | - | #:modules ((guix build utils))))) | |
| 41 | + | (user-home | |
| 42 | + | (home-type | |
| 43 | + | (name 'symlink-file) | |
| 44 | + | (extensions | |
| 45 | + | (list | |
| 46 | + | (home-extension | |
| 47 | + | (target root-home-type) | |
| 48 | + | (compute | |
| 49 | + | (const `((,from ,to)))))))) | |
| 50 | + | #t)) | |
| 47 | 51 | ||
| 48 | 52 | (define (make-ini-file name config) | |
| 49 | 53 | (define (make-ini-section name config) |