home: Add provenance home type.

Jelle LichtFri Oct 09 00:24:58+0200 2020

ffd9e73

home: Add provenance home type. * home/provenance.scm: New file. * home.scm (<home>): Export 'home-configurations'. * doc/provenance.md: New file. * doc/README.md: Add it. Signed-off-by: Julien Lepiller <julien@lepiller.eu>

doc/README.md

6666
* [Neovim](doc/neovim.md)
6767
* [Zsh](doc/zsh.md)
6868
69+
### Reproducible builds
70+
71+
* [Provenance](doc/provenance.md)
72+
6973
### Common Issues
7074
7175
#### No Sound on the System

doc/provenance.md unknown status 1

1+
Provenance
2+
======
3+
4+
This lets you record provenance meta-data in generated homes. It adds
5+
a `.provenance` file, as well `.channels.scm` and `.home.scm` files
6+
when applicable.
7+
8+
These files allow you to recreate your home at a later point in time:
9+
10+
```bash
11+
guix time-machine --channels=.channels.scm -- home build .home.scm
12+
```
13+
14+
Main Configuration
15+
------------------
16+
17+
Provenance meta-data is automatically generated by using the
18+
`provenance-home-type` service type. 
19+
20+
**Scheme Procedure**: provenance-home-type
21+
22+
The type of service that generates provenance files for your generated
23+
home. Its value is a location object.
24+
25+
**Scheme Procedure**: (home-with-provenance h [configuration-file])
26+
27+
Return a variant of _h_ that stores its own provenance information,
28+
including _configuration-file_, if available. When
29+
_configuration-file_ is omitted, the location where _h_ is defined is
30+
used.
31+
32+
Example Configuration
33+
---------------------
34+
35+
```scheme
36+
(home-with-provenance
37+
  (home
38+
    (data-directory "/data/alice")
39+
    (configurations
40+
      (list
41+
        (user-home something-home-type ...)
42+
        ...))))
43+
```
44+
45+

home.scm

3535
            home
3636
            home?
3737
            home-data-directory
38+
            home-configurations
3839
            home-location
3940
            home-guix-symlink
4041
            home-guix-config-symlink

home/provenance.scm unknown status 1

1+
;;; Guix Home Manager.
2+
;;;
3+
;;; Copyright ?? 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Court??s <ludo@gnu.org>
4+
;;; Copyright ?? 2016 Chris Marusich <cmmarusich@gmail.com>
5+
;;; Copyright ?? 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
6+
;;; Copyright ?? 2020 Jelle Licht <jlicht@fsfe.org>
7+
;;;
8+
;;; This file is based on work found in GNU Guix.
9+
;;;
10+
;;; This program is free software: you can redistribute it and/or modify
11+
;;; it under the terms of the GNU General Public License as published by
12+
;;; the Free Software Foundation, either version 3 of the License, or
13+
;;; (at your option) any later version.
14+
;;;
15+
;;; This program is distributed in the hope that it will be useful,
16+
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18+
;;; GNU General Public License for more details.
19+
;;;
20+
;;; You should have received a copy of the GNU General Public License
21+
;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
22+
23+
(define-module (home provenance)
24+
  #:use-module (gnu services)
25+
  #:use-module (guix channels)
26+
  #:use-module (guix describe)
27+
  #:use-module (guix diagnostics)
28+
  #:autoload   (guix openpgp) (openpgp-format-fingerprint)
29+
  #:use-module (guix gexp)
30+
  #:use-module (guix monads)
31+
  #:use-module (guix profiles)
32+
  #:use-module (guix records)
33+
  #:use-module (guix store)
34+
  #:use-module (home)
35+
  #:autoload   (ice-9 pretty-print) (pretty-print)
36+
  #:export (provenance-home-type
37+
            home-with-provenance))
38+
39+
(define (object->pretty-string obj)
40+
  "Like 'object->string', but using 'pretty-print'."
41+
  (call-with-output-string
42+
    (lambda (port)
43+
      (pretty-print obj port))))
44+
45+
(define (channel->code channel)
46+
  "Return code to build CHANNEL, ready to be dropped in a 'channels.scm'
47+
file."
48+
  ;; Since the 'introduction' field is backward-incompatible, and since it's
49+
  ;; optional when using the "official" 'guix channel, include it if and only
50+
  ;; if we're referring to a different channel.
51+
  (let ((intro (and (not (equal? (list channel) %default-channels))
52+
                    (channel-introduction channel))))
53+
    `(channel (name ',(channel-name channel))
54+
              (url ,(channel-url channel))
55+
              (branch ,(channel-branch channel))
56+
              (commit ,(channel-commit channel))
57+
              ,@(if intro
58+
                    `((introduction
59+
                       (make-channel-introduction
60+
                        ,(channel-introduction-first-signed-commit intro)
61+
                        (openpgp-fingerprint
62+
                         ,(openpgp-format-fingerprint
63+
                           (channel-introduction-first-commit-signer
64+
                            intro))))))
65+
                    '()))))
66+
67+
(define (channel->sexp channel)
68+
  "Return an sexp describing CHANNEL.  The sexp is _not_ code and is meant to
69+
be parsed by tools; it's potentially more future-proof than code."
70+
  ;; TODO: Add CHANNEL's introduction.  Currently we can't do that because
71+
  ;; older 'guix system describe' expect exactly name/url/branch/commit
72+
  ;; without any additional fields.
73+
  `(channel (name ,(channel-name channel))
74+
            (url ,(channel-url channel))
75+
            (branch ,(channel-branch channel))
76+
            (commit ,(channel-commit channel))))
77+
78+
(define (provenance-file channels configuration-file)
79+
  "Return a 'provenance' file describing CHANNELS, a list of channels, and
80+
CONFIGURATION-FILE, which can be either #f or a <local-file> containing the OS
81+
configuration being used."
82+
  (scheme-file "provenance"
83+
               #~(provenance
84+
                  (version 0)
85+
                  (channels #+@(if channels
86+
                                   (map channel->sexp channels)
87+
                                   '()))
88+
                  (configuration-file #+configuration-file))))
89+
90+
(define (provenance-entry config-file)
91+
  "Return system entries describing the operating system provenance: the
92+
channels in use and CONFIG-FILE, if it is true."
93+
  (define profile
94+
    (current-profile))
95+
96+
  (define channels
97+
    (and=> profile profile-channels))
98+
99+
  (let ((config-file (cond ((string? config-file)
100+
                            (local-file config-file "home.scm"))
101+
                           ((not config-file)
102+
                            #f)
103+
                           (else
104+
                            config-file))))
105+
     `((".provenance" ,(provenance-file channels config-file))
106+
              ,@(if channels
107+
                    `((".channels.scm"
108+
                       ,(plain-file "channels.scm"
109+
                                    (object->pretty-string
110+
                                     `(list
111+
                                       ,@(map channel->code channels))))))
112+
                    '())
113+
              ,@(if config-file
114+
                    `((".home.scm" ,config-file))
115+
                    '()))))
116+
117+
(define provenance-home-type
118+
  (home-type
119+
   (name 'provenance)
120+
   (extensions
121+
    (list
122+
     (home-extension
123+
      (target root-home-type)
124+
      (compute provenance-entry))))
125+
   (description "The provenance home type")))
126+
127+
(define (home-configuration-file h)
128+
  "Return the configuration file of H, based on its 'location' field, or #f
129+
if it could not be determined."
130+
  (let ((file (and=> (home-location h)
131+
                     location-file)))
132+
    (and file
133+
         (or (and (string-prefix? "/" file) file)
134+
             (search-path %load-path file)))))
135+
136+
(define* (home-with-provenance h
137+
                               #:optional
138+
                               (configuration-file
139+
                                (home-configuration-file h)))
140+
  "Return a variant of H that stores its own provenance information,
141+
including CONFIGURATION-FILE, if available.  This is achieved by adding an
142+
instance of PROVENANCE-HOME-TYPE to its configurations."
143+
  (home
144+
   (inherit h)
145+
   (configurations (cons (user-home provenance-home-type configuration-file)
146+
                         (home-configurations h)))))