guix-home-manager/home.diff

home.diff

1
diff --git a/README.md b/README.md
2
index 6bd9d93..0a0e610 100644
3
--- a/README.md
4
+++ b/README.md
5
@@ -41,21 +41,25 @@ section of this project:
6
 
7
 ### Making some room in your home directory
8
 
9
-It is recommended to use this in a new install, when your home directory is
10
-still pretty empty. Since your home directory will be made into a Guix profile,
11
-you first want to create a new directory for your user data, for instance as
12
-root:
13
+Your home directory will be completely taken over by Guix.  In particular, when
14
+using the home manager, your home directory is entirely read-only.  A read-only
15
+home directory is not very useful though, so users of the home manager will have
16
+to use a separate directory for their documents, caches and states.  This is
17
+typically `/data/alice` for user alice.
18
+
19
+It is not required to set up that directory beforehand, but if you do, you will
20
+not be able to use the home manager until you have completely wiped-out your
21
+home directory (i.e. transfered it to the new directory).  If the directory
22
+does not yet exist, your current home directory is automatically renamed to
23
+that directory, and the home manager starts working.
24
+
25
+Basically, you will run (as root):
26
 
27
 ```bash
28
-mkdir -p /data/alice
29
-chown alice: /data/alice
30
+mkdir /data
31
+mv /home/alice /data/alice
32
 ```
33
 
34
-if your user is named alice. Then, move all your data over to that directory.
35
-Do not transfer your configuration, it will be useless. That transfering of data
36
-is the reason why it's simpler to start with an empty home: there is no data to
37
-transfer ;)
38
-
39
 Once that is done, some parts of your home directory will still have to be
40
 read-write. This is mostly `~/.cache`, `~/.local` but also `~/.guix-profile` and
41
 `~/.config/guix`. Inside your new data directory, create them like this, as your
42
@@ -66,6 +70,13 @@ cd /data/alice
43
 mkdir-p .local/share .cache .config
44
 ```
45
 
46
+Since you have moved your entire home directory, make sure you can still access
47
+your own copy of guix and your user profile by (temporarily) setting your
48
+`$PATH` (make sure it starts with `/data/alice/.config/guix/current/bin`) and
49
+by sourcing the profile with `export GUIX_PROFILE=/data/alice/.guix-profile;
50
+source $GUIX_PROFILE/etc/profile`.  You might also need to run `hash -r`
51
+(no output) for bash to clear all its memorized binary locations.
52
+
53
 ### Creating the first home generation
54
 
55
 To create your first home configuration, you must create a configuration file.
56
@@ -74,8 +85,8 @@ For instance, create `/data/alice/.config/guix/home.scm`:
57
 ```scheme
58
 (use-modules (home))
59
 
60
-(home "/data/alice"
61
-  '())
62
+(home
63
+  (data-directory "/data/alice"))
64
 ```
65
 
66
 This will generate a completely empty home, except for essential configurations,
67
@@ -87,23 +98,7 @@ To build your first generation of your home environment, run as your regular
68
 user:
69
 
70
 ```bash
71
-guix package -p /var/guix/profiles/per-user/alice/home \
72
-  -f /data/alice/.config/guix/home.scm
73
-```
74
-
75
-Still as your regular user, copy your `~/.config/guix` to your data directory.
76
-This will ensure you can still use Guix after you switch to the managed home
77
-profile:
78
-
79
-```bash
80
-cp -ar ~/.config/guix /data/alice/.config/
81
-```
82
-
83
-Finaly, switch to the managed home profile as root:
84
-
85
-```bash
86
-mv /home/alice{,.bak} # keep a backup in case something goes wrong
87
-ln -sv /var/guix/profiles/per-user/alice/home /home/alice
88
+guix home reconfigure /data/alice/.config/guix/home.scm
89
 ```
90
 
91
 That's it!
92
@@ -121,4 +116,4 @@ over the world!
93
 
94
 If you are less into code, we welcome contributions in the form of documentation,
95
 translation, issues, reviews, tips and tricks. Do not hesitate to get in touch if
96
-you have an idea or want to help in any way!
97
\ No newline at end of file
98
+you have an idea or want to help in any way!
99
diff --git a/doc/README.md b/doc/README.md
100
index 1ade3a5..384294a 100644
101
--- a/doc/README.md
102
+++ b/doc/README.md
103
@@ -36,12 +36,14 @@ with "-home", you know that you can use it in the list of configurations, like
104
 this:
105
 
106
 ```scheme
107
-(home "/data/alice"
108
-  (list (something-home ...)
109
-        (something-else-home ...)
110
-        (other-stuff-home ...)
111
-        (yet-another-config-home ...)
112
-        ...))
113
+(home
114
+  (data-directory "/data/alice")
115
+  (configurations
116
+    (list (something-home ...)
117
+          (something-else-home ...)
118
+          (other-stuff-home ...)
119
+          (yet-another-config-home ...)
120
+          ...)))
121
 ```
122
 
123
 #### Desktop and Window Managers
124
@@ -69,4 +71,4 @@ Unfortunately, that means you cannot configure pulseaudio through Guix. You can
125
 also add a similar line to your desktop or window manager's configuration to
126
 instruct it to start pulseaudio. However, pulseaudio sometimes crashes for non
127
 obvious reasons, and no graphical program will be able to restart it automatically
128
-with a proper configuration.
129
\ No newline at end of file
130
+with a proper configuration.
131
diff --git a/doc/general.md b/doc/general.md
132
index f6abd1b..23fd91f 100644
133
--- a/doc/general.md
134
+++ b/doc/general.md
135
@@ -66,8 +66,8 @@ Build-side Utilities
136
 The `(home build utils)` extends the utilities provided by `(guix build utils)`
137
 with the following procedure:
138
 
139
-**Scheme Procedure**: (home-file outputs path ...)
140
+**Scheme Procedure**: (home-file output path ...)
141
 
142
-Return the complete path to the output of a package being defined by adding
143
-"/" between each component of _path_. _outputs_ is the content of `%build-output`
144
-in the package definition. This is not very useful for end users.
145
+Return the complete path to the output of a gexp being defined by adding
146
+"/" between each component of _path_. _output_ is the content of `#$output`
147
+in the package definition.
148
diff --git a/doc/install.md b/doc/install.md
149
index 16b8149..bda7456 100644
150
--- a/doc/install.md
151
+++ b/doc/install.md
152
@@ -28,21 +28,25 @@ Usage
153
 
154
 ### Making some room in your home directory
155
 
156
-It is recommended to use this in a new install, when your home directory is
157
-still pretty empty. Since your home directory will be made into a Guix profile,
158
-you first want to create a new directory for your user data, for instance as
159
-root:
160
+Your home directory will be completely taken over by Guix.  In particular, when
161
+using the home manager, your home directory is entirely read-only.  A read-only
162
+home directory is not very useful though, so users of the home manager will have
163
+to use a separate directory for their documents, caches and states.  This is
164
+typically `/data/alice` for user alice.
165
+
166
+It is not required to set up that directory beforehand, but if you do, you will
167
+not be able to use the home manager until you have completely wiped-out your
168
+home directory (i.e. transfered it to the new directory).  If the directory
169
+does not yet exist, your current home directory is automatically renamed to
170
+that directory, and the home manager starts working.
171
+
172
+Basically, you will run (as root):
173
 
174
 ```bash
175
-mkdir -p /data/alice
176
-chown alice: /data/alice
177
+mkdir /data
178
+mv /home/alice /data/alice
179
 ```
180
 
181
-if your user is named alice. Then, move all your data over to that directory.
182
-Do not transfer your configuration, it will be useless. That transfering of data
183
-is the reason why it's simpler to start with an empty home: there is no data to
184
-transfer ;)
185
-
186
 Once that is done, some parts of your home directory will still have to be
187
 read-write. This is mostly `~/.cache`, `~/.local` but also `~/.guix-profile` and
188
 `~/.config/guix`. Inside your new data directory, create them like this, as your
189
@@ -53,6 +57,13 @@ cd /data/alice
190
 mkdir-p .local/share .cache .config
191
 ```
192
 
193
+Since you have moved your entire home directory, make sure you can still access
194
+your own copy of guix and your user profile by (temporarily) setting your
195
+`$PATH` (make sure it starts with `/data/alice/.config/guix/current/bin`) and
196
+by sourcing the profile with `export GUIX_PROFILE=/data/alice/.guix-profile;
197
+source $GUIX_PROFILE/etc/profile`.  You might also need to run `hash -r`
198
+(no output) for bash to clear all its memorized binary locations.
199
+
200
 ### Creating the first home generation
201
 
202
 To create your first home configuration, you must create a configuration file.
203
@@ -61,8 +72,8 @@ For instance, create `/data/alice/.config/guix/home.scm`:
204
 ```scheme
205
 (use-modules (home))
206
 
207
-(home "/data/alice"
208
-  '())
209
+(home
210
+  (data-directory "/data/alice"))
211
 ```
212
 
213
 This will generate a completely empty home, except for essential configurations,
214
@@ -74,23 +85,7 @@ To build your first generation of your home environment, run as your regular
215
 user:
216
 
217
 ```bash
218
-guix package -p /var/guix/profiles/per-user/alice/home \
219
-  -f /data/alice/.config/guix/home.scm
220
+guix home reconfigure /data/alice/.config/guix/home.scm
221
 ```
222
 
223
-Still as your regular user, copy your `~/.config/guix` to your data directory.
224
-This will ensure you can still use Guix after you switch to the managed home
225
-profile:
226
-
227
-```bash
228
-cp -ar ~/.config/guix /data/alice/.config/
229
-```
230
-
231
-Finaly, switch to the managed home profile as root:
232
-
233
-```bash
234
-mv /home/alice{,.bak} # keep a backup in case something goes wrong
235
-ln -sv /var/guix/profiles/per-user/alice/home /home/alice
236
-```
237
-
238
-That's it!
239
\ No newline at end of file
240
+That's it!
241
diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm
242
index d4b54ea..76a7fe5 100644
243
--- a/guix/scripts/home.scm
244
+++ b/guix/scripts/home.scm
245
@@ -17,9 +17,21 @@
246
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
247
 
248
 (define-module (guix scripts home)
249
+  #:use-module (guix derivations)
250
+  #:use-module (guix grafts)
251
+  #:use-module (guix monads)
252
+  #:use-module (guix packages)
253
+  #:use-module (guix profiles)
254
   #:use-module (guix scripts)
255
+  #:use-module (guix scripts build)
256
+  #:use-module (guix status)
257
+  #:use-module (guix store)
258
   #:use-module (guix ui)
259
   #:use-module (guix utils)
260
+  #:use-module (home)
261
+  #:use-module (ice-9 match)
262
+  #:use-module (srfi srfi-1)
263
+  #:use-module (srfi srfi-26)
264
   #:use-module (srfi srfi-37)
265
   #:export (guix-home))
266
 
267
@@ -37,8 +49,16 @@
268
                   (show-version-and-exit "guix edit")))))
269
 
270
 (define (show-help)
271
-  (display (G_ "Usage: guix home CONFIG
272
-Manage a user home environment according to CONFIG\n"))
273
+  (display (G_ "Usage: guix home [OPTION ...] ACTION [ARG ...] [FILE]
274
+Manage a user home environment according to FILE and ACTION.  Some actions
275
+support additional ARGs.\n"))
276
+  (display (G_ "The valid values for ACTION are:\n"))
277
+  (newline)
278
+  (display (G_ "\
279
+   reconfigure      switch to or create a new home configuration\n"))
280
+  (display (G_ "\
281
+   build            build the home configuration without installing anything\n"))
282
+  (show-build-options-help)
283
   (display (G_ "
284
   -h, --help             display this help and exit"))
285
   (display (G_ "
286
@@ -46,19 +66,276 @@ Manage a user home environment according to CONFIG\n"))
287
   (newline)
288
   (show-bug-report-information))
289
 
290
+(define %options
291
+  ;; Specifications of the command-line options.
292
+  (cons* (option '(#\h "help") #f #f
293
+                 (lambda args
294
+                   (show-help)
295
+                   (exit 0)))
296
+         (option '(#\V "version") #f #f
297
+                 (lambda args
298
+                   (show-version-and-exit "guix system")))
299
+         (option '(#\e "expression") #t #f
300
+                 (lambda (opt name arg result)
301
+                   (alist-cons 'expression arg result)))
302
+         (option '(#\d "derivation") #f #f
303
+                 (lambda (opt name arg result)
304
+                   (alist-cons 'derivations-only? #t result)))
305
+         (option '("on-error") #t #f
306
+                 (lambda (opt name arg result)
307
+                   (alist-cons 'on-error (string->symbol arg)
308
+                               result)))
309
+         (option '(#\t "file-system-type") #t #f
310
+                 (lambda (opt name arg result)
311
+                   (alist-cons 'file-system-type arg
312
+                               result)))
313
+         (option '("image-size") #t #f
314
+                 (lambda (opt name arg result)
315
+                   (alist-cons 'image-size (size->number arg)
316
+                               result)))
317
+         (option '(#\N "network") #f #f
318
+                 (lambda (opt name arg result)
319
+                   (alist-cons 'container-shared-network? #t result)))
320
+         (option '("no-bootloader" "no-grub") #f #f
321
+                 (lambda (opt name arg result)
322
+                   (alist-cons 'install-bootloader? #f result)))
323
+         (option '("full-boot") #f #f
324
+                 (lambda (opt name arg result)
325
+                   (alist-cons 'full-boot? #t result)))
326
+         (option '("skip-checks") #f #f
327
+                 (lambda (opt name arg result)
328
+                   (alist-cons 'skip-safety-checks? #t result)))
329
+
330
+         (option '("share") #t #f
331
+                 (lambda (opt name arg result)
332
+                   (alist-cons 'file-system-mapping
333
+                               (specification->file-system-mapping arg #t)
334
+                               result)))
335
+         (option '("expose") #t #f
336
+                 (lambda (opt name arg result)
337
+                   (alist-cons 'file-system-mapping
338
+                               (specification->file-system-mapping arg #f)
339
+                               result)))
340
+
341
+         (option '(#\n "dry-run") #f #f
342
+                 (lambda (opt name arg result)
343
+                   (alist-cons 'dry-run? #t (alist-cons 'graft? #f result))))
344
+         (option '(#\v "verbosity") #t #f
345
+                 (lambda (opt name arg result)
346
+                   (let ((level (string->number* arg)))
347
+                     (alist-cons 'verbosity level
348
+                                 (alist-delete 'verbosity result)))))
349
+         (option '(#\s "system") #t #f
350
+                 (lambda (opt name arg result)
351
+                   (alist-cons 'system arg
352
+                               (alist-delete 'system result eq?))))
353
+         (option '(#\r "root") #t #f
354
+                 (lambda (opt name arg result)
355
+                   (alist-cons 'gc-root arg result)))
356
+         %standard-build-options))
357
+
358
 (define %default-options
359
-  `((system    . ,(%current-system))))
360
+  ;; Alist of default option values.
361
+  `((system . ,(%current-system))
362
+    (substitutes? . #t)
363
+    (build-hook? . #t)
364
+    (print-build-trace? . #t)
365
+    (print-extended-build-trace? . #t)
366
+    (multiplexed-build-output? . #t)
367
+    (graft? . #t)
368
+    (debug . 0)
369
+    (verbosity . #f)                              ;default
370
+    (file-system-type . "ext4")
371
+    (image-size . guess)
372
+    (install-bootloader? . #t)))
373
+
374
+;;;
375
+;;; Profiles
376
+;;;
377
+
378
+(define %user-module
379
+  ;; Module in which the machine description file is loaded.
380
+  (make-user-module '()))
381
+
382
+(define %home (getenv "HOME"))
383
+
384
+(define %current-home
385
+  (string-append %profile-directory "/home"))
386
+
387
+(define (ensure-home-profile data-directory)
388
+  "Ensures $HOME is a symlink to the profile.  If it is not yet the case, move
389
+it to the @var{data-directory} directory, unless it already exists, in which case
390
+report an error."
391
+  (ensure-profile-directory)
392
+
393
+  (when %home %current-home
394
+    (let ((home (false-if-exception (lstat %home))))
395
+      (if home
396
+          (if (false-if-exception (lstat data-directory))
397
+            (rename-file %home data-directory)
398
+            (leav (G_ "Your $HOME directory (~a) is not a symlink to a profile,
399
+and it cannot be moved as ~a already exists on the filesystem.~%")
400
+                  %home data-directory))
401
+          (symlink %current-home %home)))))
402
 
403
 ;;;
404
 ;;; Entry point.
405
 ;;;
406
 
407
+(define* (perform-action action home
408
+                         #:key
409
+                         dry-run? derivations-only?
410
+                         use-substitutes?)
411
+  "Perform ACTION for HOME.  When DERIVATIONS-ONLY? is true, print the
412
+derivation file name(s) without building anything."
413
+  (define println
414
+    (cut format #t "~a~%" <>))
415
+
416
+  (when (eq? action 'reconfigure)
417
+    (ensure-home-profile (home-data-directory home))
418
+    (maybe-suggest-running-guix-pull))
419
+
420
+  (with-store store
421
+    (let* ((drv      (run-with-store store (home->derivation home)))
422
+           (profile  (derivation->output-path drv)))
423
+      (show-what-to-build store (list drv)
424
+                          #:use-substitutes? use-substitutes?
425
+                          #:dry-run? dry-run?)
426
+
427
+      (unless (or dry-run? derivations-only?)
428
+          (begin
429
+            (build-derivations store (list drv))
430
+            (case action
431
+              ((reconfigure)
432
+               (newline)
433
+               (format #t (G_ "activating home...~%"))
434
+               (let ((number (generation-number %current-home))
435
+                     (generation (generation-file-name %current-home number)))
436
+                 (switch-symlinks generation profile)
437
+                 (switch-symlinks %current-home generation)))
438
+              (else
439
+                (display profile)
440
+                (newline))))))))
441
+
442
+(define (process-action action args opts)
443
+  "Process ACTION, a sub-command, with the arguments are listed in ARGS.
444
+ACTION must be one of the sub-commands that takes an operating system
445
+declaration as an argument (a file name.)  OPTS is the raw alist of options
446
+resulting from command-line parsing."
447
+  (define (ensure-home-configuration file-or-exp obj)
448
+    (unless (home? obj)
449
+      (leave (G_ "'~a' does not return a home configuration~%")
450
+             file-or-exp))
451
+    obj)
452
+
453
+  (let* ((file        (match args
454
+                        (() #f)
455
+                        ((x . _) x)))
456
+         (expr        (assoc-ref opts 'expression))
457
+         (system      (assoc-ref opts 'system))
458
+         (home        (ensure-home-configuration
459
+                       (or file expr)
460
+                       (cond
461
+                        ((and expr file)
462
+                         (leave
463
+                          (G_ "both file and expression cannot be specified~%")))
464
+                        (expr
465
+                         (read/eval expr))
466
+                        (file
467
+                         (load* file %user-module
468
+                                #:on-error (assoc-ref opts 'on-error)))
469
+                        (else
470
+                         (leave (G_ "no configuration specified~%"))))))
471
+
472
+         (dry?        (assoc-ref opts 'dry-run?)))
473
+
474
+    (with-store store
475
+      (set-build-options-from-command-line store opts)
476
+
477
+      (set-guile-for-build (default-guile))
478
+
479
+      (case action
480
+        (else
481
+         (unless (eq? action 'build)
482
+           (warn-about-old-distro #:suggested-command
483
+                                  "guix home reconfigure"))
484
+
485
+         (perform-action action home
486
+                         #:dry-run? dry?
487
+                         #:derivations-only? (assoc-ref opts
488
+                                                        'derivations-only?)
489
+                         #:use-substitutes? (assoc-ref opts 'substitutes?)))))
490
+    (warn-about-disk-space)))
491
+
492
+(define (resolve-subcommand name)
493
+  (let ((module (resolve-interface
494
+                 `(guix scripts home ,(string->symbol name))))
495
+        (proc (string->symbol (string-append "guix-home-" name))))
496
+    (module-ref module proc)))
497
+
498
+(define (process-command command args opts)
499
+  "Process COMMAND, one of the 'guix system' sub-commands.  ARGS is its
500
+argument list and OPTS is the option alist."
501
+  (case command
502
+    ;; The following commands do not need to use the store, and they do not need
503
+    ;; an operating system configuration file.
504
+    ;; The following commands need to use the store, but they do not need an
505
+    ;; operating system configuration file.
506
+    ;; The following commands need to use the store, and they also
507
+    ;; need an operating system configuration file.
508
+    (else (process-action command args opts))))
509
+
510
 (define (guix-home . args)
511
+  (define (parse-sub-command arg result)
512
+    ;; Parse sub-command ARG and augment RESULT accordingly.
513
+    (if (assoc-ref result 'action)
514
+        (alist-cons 'argument arg result)
515
+        (let ((action (string->symbol arg)))
516
+          (case action
517
+            ((build reconfigure)
518
+             (alist-cons 'action action result))
519
+            (else (leave (G_ "~a: unknown action~%") action))))))
520
+
521
+  (define (match-pair car)
522
+    ;; Return a procedure that matches a pair with CAR.
523
+    (match-lambda
524
+      ((head . tail)
525
+       (and (eq? car head) tail))
526
+      (_ #f)))
527
+
528
+  (define (option-arguments opts)
529
+    ;; Extract the plain arguments from OPTS.
530
+    (let* ((args   (reverse (filter-map (match-pair 'argument) opts)))
531
+           (count  (length args))
532
+           (action (assoc-ref opts 'action))
533
+           (expr   (assoc-ref opts 'expression)))
534
+      (define (fail)
535
+        (leave (G_ "wrong number of arguments for action '~a'~%")
536
+               action))
537
+
538
+      (unless action
539
+        (format (current-error-port)
540
+                (G_ "guix home: missing command name~%"))
541
+        (format (current-error-port)
542
+                (G_ "Try 'guix home --help' for more information.~%"))
543
+        (exit 1))
544
+
545
+      (case action
546
+        ((build reconfigure)
547
+         (unless (= count 1)
548
+           (fail))))
549
+      args))
550
+
551
   (with-error-handling
552
     (let* ((opts     (parse-command-line args %options
553
                                          (list %default-options)
554
-                                         #:build-options? #f)))
555
-      (format #t "Guix Home Test~%")))
556
-  #t)
557
+                                         #:argument-handler
558
+                                         parse-sub-command))
559
+           (args     (option-arguments opts))
560
+           (command  (assoc-ref opts 'action)))
561
+      (parameterize ((%graft? (assoc-ref opts 'graft?)))
562
+        (with-status-verbosity (or (assoc-ref opts 'verbosity)
563
+                                   (if (eq? command 'build) 2 1))
564
+          (process-command command args opts))))))
565
 
566
 ;;; home.scm ends here
567
diff --git a/home.scm b/home.scm
568
index 0a3c03a..99ff98f 100644
569
--- a/home.scm
570
+++ b/home.scm
571
@@ -22,56 +22,71 @@
572
   #:use-module (guix gexp)
573
   #:use-module (guix licenses)
574
   #:use-module (guix packages)
575
+  #:use-module (guix records)
576
+  #:use-module (ice-9 match)
577
   #:use-module (home build utils)
578
-  #:export (home
579
-            use-home-modules))
580
+  #:export (use-home-modules
581
+            home
582
+            home?
583
+            home-data-directory
584
+            home-guix-symlink
585
+            home-guix-config-symlink
586
+            home-local-symlink
587
+            home-cache-symlink
588
+            home->derivation))
589
 
590
 (define-syntax use-home-modules
591
   (syntax-rules ()
592
     ((_ modules ...)
593
      (use-modules (home modules) ...))))
594
 
595
-(define* (home basedir inputs #:key
596
-               (guix-symlink (string-append basedir "/.guix-profile"))
597
-               (guix-config-symlink (string-append basedir "/.config/guix"))
598
-               (local-symlink (string-append basedir "/.local"))
599
-               (cache-symlink (string-append basedir "/.cache")))
600
-  (define union
601
-    (computed-file "home"
602
+(define-record-type* <home> home
603
+  make-home
604
+  home?
605
+  (data-directory home-data-directory)
606
+  (guix-symlink   home-guix-symlink (thunked)
607
+                  (default (string-append
608
+                             (home-data-directory this-record)
609
+                             "/.guix-profile")))
610
+  (guix-config-symlink home-guix-config-symlink (thunked)
611
+                       (default (string-append
612
+                                  (home-data-directory this-record)
613
+                                  "/.config/guix")))
614
+  (local-symlink  home-local-symlink (thunked)
615
+                  (default (string-append
616
+                             (home-data-directory this-record)
617
+                             "/.local")))
618
+  (cache-symlink  home-cache-symlink (thunked)
619
+                  (default (string-append
620
+                             (home-data-directory this-record)
621
+                             "/.cache")))
622
+  (configurations home-configurations
623
+                  (default '())))
624
+
625
+(define (home->derivation home)
626
+  (define builder
627
+    (with-imported-modules
628
+      '((guix build utils) (home build utils))
629
       #~(begin
630
-          (use-modules (guix build union))
631
-          (union-build #$output '#$inputs))
632
-      #:options
633
-      '(#:local-build? #t
634
-        #:modules ((guix build union)))))
635
-  (package
636
-    (name "guix-home")
637
-    (version "0")
638
-    (source #f)
639
-    (build-system trivial-build-system)
640
-    (arguments
641
-     `(#:modules ((guix build utils) (home build utils))
642
-       #:builder
643
-       (begin
644
-         (use-modules (guix build utils) (home build utils))
645
-         (mkdir-p (home-file %outputs ".config"))
646
-         ;; For guix
647
-         (symlink ,guix-config-symlink (home-file %outputs ".config/guix"))
648
-         (symlink ,guix-symlink (home-file %outputs ".guix-profile"))
649
-         ;; symlink writeable directories
650
-         (symlink ,local-symlink (home-file %outputs ".local"))
651
-         (symlink ,cache-symlink (home-file %outputs ".cache"))
652
-         ;; rest of the files
653
-         (with-directory-excursion (assoc-ref %build-inputs "union")
654
-         (for-each
655
-           (lambda (f)
656
-             (mkdir-p (home-file %outputs (dirname f)))
657
-             (symlink (string-append (assoc-ref %build-inputs "union") "/" f)
658
-                      (home-file %outputs f)))
659
-           (find-files "." ".*"))))))
660
-    (inputs
661
-     `(("union" ,union)))
662
-    (home-page "")
663
-    (synopsis "")
664
-    (description "")
665
-    (license gpl3+)))
666
\ No newline at end of file
667
+          (use-modules (guix build utils) (home build utils))
668
+          (mkdir-p (home-file #$output ".config"))
669
+          ;; For guix
670
+          (symlink #$(home-guix-config-symlink home) (home-file #$output ".config/guix"))
671
+          (symlink #$(home-guix-symlink home) (home-file #$output ".guix-profile"))
672
+          ;; symlink writeable directories
673
+          (symlink #$(home-local-symlink home) (home-file #$output ".local"))
674
+          (symlink #$(home-cache-symlink home) (home-file #$output ".cache"))
675
+          ;; rest of the files
676
+          (for-each
677
+            (lambda (config)
678
+              (with-directory-excursion config
679
+                (for-each
680
+                  (lambda (f)
681
+                    (mkdir-p (home-file #$output (dirname f)))
682
+                    (symlink (home-file config f)
683
+                             (home-file #$output f)))
684
+                  (find-files "." "."))))
685
+            (list #$@(home-configurations home))))))
686
+  (gexp->derivation "home" builder
687
+                    #:substitutable? #f
688
+                    #:local-build? #t))
689
diff --git a/home/build/utils.scm b/home/build/utils.scm
690
index 19b66a9..832af28 100644
691
--- a/home/build/utils.scm
692
+++ b/home/build/utils.scm
693
@@ -18,5 +18,5 @@
694
 (define-module (home build utils)
695
   #:export (home-file))
696
 
697
-(define (home-file outputs . path)
698
-  (apply string-append (assoc-ref outputs "out") "/" path))
699
\ No newline at end of file
700
+(define (home-file output . path)
701
+  (apply string-append output "/" path))
702