[WIP] home: Add home-git-service-type

  • Open
  • quality assurance status badge
Details
3 participants
  • ???
  • Ludovic Courtès
  • Maxime Devos
Owner
unassigned
Submitted by
???
Severity
normal
?
(address . guix-patches@gnu.org)
TYCP286MB189799FE00EC37FC1D454CA2A3089@TYCP286MB1897.JPNP286.PROD.OUTLOOK.COM
Hello, with:
Toggle snippet (6 lines)
(service home-git-service-type
(home-git-configuration
(options '((user (name "foo")
(email "foo@bar.com"))))))

We'll have git in the home profile, and GIT_CONFIG_SYSTEM pointing to a
file contains:
Toggle snippet (5 lines)
[user]
name = "foo"
email = "foo@bar.com"

Which set the system-level options for git.
From d161786c675a12f9cb2bce2bdb965d65eb5281ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=8B=E6=96=87=E6=AD=A6?= <iyzsong@member.fsf.org>
Date: Mon, 7 Mar 2022 22:14:09 +0800
Subject: [PATCH] home: Add home-git-service-type.

* gnu/home/services/git.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/home/services/git.scm | 95 +++++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
2 files changed, 96 insertions(+)
create mode 100644 gnu/home/services/git.scm

Toggle diff (115 lines)
diff --git a/gnu/home/services/git.scm b/gnu/home/services/git.scm
new file mode 100644
index 0000000000..2c3f87fbab
--- /dev/null
+++ b/gnu/home/services/git.scm
@@ -0,0 +1,95 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 ??? <iyzsong@member.fsf.org>
+;;;
+;;; 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 home services git)
+ #:use-module (gnu home services)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu packages version-control)
+ #:use-module (guix packages)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (ice-9 match)
+ #:export (home-git-service-type
+ home-git-configuration))
+
+(define (git-options? options)
+ "Return #t if OPTIONS is a well-formed sexp for git options."
+ (define git-variable?
+ (match-lambda
+ ((key value) (and (symbol? key) (string? value)))
+ (_ #f)))
+ (every
+ (match-lambda
+ (((section subsection) variables ..1)
+ (and (symbol? section)
+ (string? subsection)
+ (every git-variable? variables)))
+ ((section variables ..1)
+ (and (symbol? section)
+ (every git-variable? variables)))
+ (_ #f))
+ options))
+
+(define (serialize-git-options options)
+ (define serialize-section
+ (match-lambda
+ ((section variables ..1)
+ (with-output-to-string
+ (lambda ()
+ (match section
+ ((section subsection)
+ (simple-format #t "[~a ~s]~%" section subsection))
+ (_
+ (simple-format #t "[~a]~%" section)))
+ (for-each
+ (match-lambda
+ ((key value)
+ (simple-format #t "\t~a = ~s~%" key value)))
+ variables))))))
+ (string-concatenate (map serialize-section options)))
+
+(define-configuration home-git-configuration
+ (package
+ (package git)
+ "The Git package to use.")
+ (options
+ (git-options '())
+ "System configuration options for Git."))
+
+
+(define (home-git-environment-variables config)
+ (let ((gitconfig (serialize-git-options
+ (home-git-configuration-options config))))
+ `(("GIT_CONFIG_SYSTEM" . ,(plain-file "gitconfig" gitconfig)))))
+
+(define (home-git-profile config)
+ (list (home-git-configuration-package config)))
+
+(define home-git-service-type
+ (service-type (name 'home-git)
+ (extensions
+ (list (service-extension
+ home-environment-variables-service-type
+ home-git-environment-variables)
+ (service-extension
+ home-profile-service-type
+ home-git-profile)))
+ (default-value (home-git-configuration))
+ (description
+ "Install and configure the Git distributed revision control
+system.")))
diff --git a/gnu/local.mk b/gnu/local.mk
index 9bfeede60f..a5ea94b3a1 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -80,6 +80,7 @@ GNU_SYSTEM_MODULES = \
%D%/home.scm \
%D%/home/services.scm \
%D%/home/services/desktop.scm \
+ %D%/home/services/git.scm \
%D%/home/services/symlink-manager.scm \
%D%/home/services/fontutils.scm \
%D%/home/services/shells.scm \
--
2.34.0
I made 'options' an sexp value since there are so many git options (see
'man git-config'). When `options' is invalid, `guix home' will reports:
'guix home: error: Invalid value for field options: ......', is this
acceptable or how to make a better validation error report?

I can also symlink the generated gitconfig into ~/.gitconfig, but with
'GIT_CONFIG_SYSTEM' it can be used together with hand maintained
~/.gitconfig.

Documentation is lacking, I'm still bad at them...

Any interest or review feedback? Thanks!

I'd like to write more home services for msmtp, emacs, foot, etc. to
configure my whole user session :)
M
M
Maxime Devos wrote on 7 Mar 2022 18:58
a7fdfcfb23c47227f7d0e19eda6688783980f58e.camel@telenet.be
??? schreef op ma 07-03-2022 om 22:51 [+0800]:
Toggle quote (5 lines)
> +           (for-each
> +            (match-lambda
> +              ((key value)
> +               (simple-format #t "\t~a = ~s~%" key value)))

What if I want to set the key 'bar' to the value 'foo bar ' (without
teh quotes, but with the trailing space)? If I do ‘git config
'foo.bar' "foo bar "’, then the following is added to .git/config:

[foo]
bar = "foo bar "

so it seems that some escaping may be necessary.

Also, what character encoding does git expect .git/config expect it to
be in? UTF-8, whatever the current locale's encoding is, ...?

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYiZHwhccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7vjDAP4xrRErdFEgkiuIsyECMvRCWvlz
i/N/OXgpWiDbRmarwgD+IKnNpiRFbReFoXSx1rGM0iENmyjbMri7n0seNQJzrgg=
=11KE
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 7 Mar 2022 19:01
c2e3a4bf52d46503c3ead620254adc1e35f21b0d.camel@telenet.be
??? schreef op ma 07-03-2022 om 22:51 [+0800]:
Toggle quote (4 lines)
> +  (options
> +   (git-options '())
> +   "System configuration options for Git."))

Instead of this ad-hoc alist structure, how about introducing some
structure with records, like done for other Guix services, e.g.
'openssh-configuration' and 'guix-configuration'?

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYiZIXRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7h5GAQDKhq/11yJq3r3rilLgxDGmxy0S
9H7uSA3X17irwP4edQD/TLqPBQZqtftAI8kKmfGhprQJMmFkVI6twnx7Fp0teQc=
=aVHY
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 7 Mar 2022 19:02
4e224f5bc48ffbd9f0df21eae96fc5afec251546.camel@telenet.be
??? schreef op ma 07-03-2022 om 22:51 [+0800]:
Toggle quote (3 lines)
> I made 'options' an sexp value since there are so many git options
> (see 'man git-config').

This can be solved with an escape hatch like openssh-configuration's
'extra-content' and by adding support for new options on an on-demand
basis. If there are lots of options, that just means there's lot to
do, I think.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYiZIwhccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7ugCAQCWKe/PTl/WDh8+bHgY0OK0aYv7
p3AWw2sWTpvtQGBdKwD7BVe6Xhpr/9JO0zfv+HlLFlISoy5fCIBGBi+Dt/lcnwY=
=6xfB
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 7 Mar 2022 19:04
0bac942818fbe46196f420a1df6632a860ae29a1.camel@telenet.be
??? schreef op ma 07-03-2022 om 22:51 [+0800]:
Toggle quote (4 lines)
> I can also symlink the generated gitconfig into ~/.gitconfig, but
> with 'GIT_CONFIG_SYSTEM' it can be used together with hand maintained
> ~/.gitconfig.

The GIT_CONFIG_SYSTEM is less stateful, I like it. There are multiple
variables like these though: GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM and
GIT_CONFIG. My guess is that GIT_CONFIG_GLOBAL would be appropriate
here.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYiZJPhccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7pZdAP4pD8en/OfbVflwaVZlBQvg0D5I
MUJaWxNySrehRGhyAgEA8G5cUUNw/AY+ySJqcCfSIx6VA38T6P1fIwZ58jrjogE=
=3+ru
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 7 Mar 2022 19:11
4802fd5bd14e6d73ca8205edab1e38580db7dd0c.camel@telenet.be
??? schreef op ma 07-03-2022 om 22:51 [+0800]:
Toggle quote (7 lines)
> Hello, with:
> --8<---------------cut here---------------start------------->8---
> (service home-git-service-type
>  (home-git-configuration
>   (options '((user (name "foo")
>                    (email "foo@bar.com")))))) [...]

How about providing an option for passwords? E.g.,

(home-git-configuration
(user (git-user-info
(name "Foobar")
(e-mail "Foobar <foo@bar.com>")
(signing-key "some PGP fingerprint)))
(secrets-file "/home/foo/the-password")
(smtp (git-smtp-configuration
#;(password "12345") ; not recommended, use 'secrets-file' instead
...))

(with some appropriate documentation)

secrets-file (not interned in the store):
# I don't remember the exact option name
smtp.password = Foobaz

the produced .gitconfig would include a line

[include]
path = /home/foo/the-password
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYiZKxBccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7otOAQCOnttc3JBbFIOvNw4qXeXr72BZ
/ssGKKifN/b8UkB3kwEAn9iiJoSD3QQIHkuwYcIWZ66EEaip1AMyRSXAckPD7wo=
=V62F
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 7 Mar 2022 19:12
5efa8b6934c92e87751ca5f5c38f2ccfb750ca00.camel@telenet.be
Maxime Devos schreef op ma 07-03-2022 om 19:01 [+0100]:
Toggle quote (4 lines)
> Instead of this ad-hoc alist structure, how about introducing some
> structure with records, like done for other Guix services, e.g.
> 'openssh-configuration' and 'guix-configuration'?

To elaborate a little, I think the following options are the most
important to support:

user.name, user.email, commiter.name, committer.email
smtp things (for git send-email, important for contributing to guix)
pgp things (important for being a committer in guix)

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYiZLJxccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7sr4AQCJxOtB8qEKOK/pPF4kxoYWh7Lf
rBmcNWtLZFmHYrckgQEArPoVwXxaPa+M5xHHUKrAoKnY6SNW3k/xwSxFxyXz8g8=
=+ZqD
-----END PGP SIGNATURE-----


?
(name . Maxime Devos)(address . maximedevos@telenet.be)(address . 54293@debbugs.gnu.org)
TYCP286MB189784F08409D048990E3FBBA30A9@TYCP286MB1897.JPNP286.PROD.OUTLOOK.COM
Maxime Devos <maximedevos@telenet.be> writes:

Toggle quote (15 lines)
> ??? schreef op ma 07-03-2022 om 22:51 [+0800]:
>> +           (for-each
>> +            (match-lambda
>> +              ((key value)
>> +               (simple-format #t "\t~a = ~s~%" key value)))
>
> What if I want to set the key 'bar' to the value 'foo bar ' (without
> teh quotes, but with the trailing space)? If I do ‘git config
> 'foo.bar' "foo bar "’, then the following is added to .git/config:
>
> [foo]
> bar = "foo bar "
>
> so it seems that some escaping may be necessary.

Yes, '~s' in the format string will use 'write' which will print strings
in double quotes with some escapes. I think it's compatible with
gitconfig's requirement.

Toggle quote (4 lines)
>
> Also, what character encoding does git expect .git/config expect it to
> be in? UTF-8, whatever the current locale's encoding is, ...?

I guess it expect UTF-8, will do some tests later, thanks!
?
(name . Maxime Devos)(address . maximedevos@telenet.be)(address . 54293@debbugs.gnu.org)
TYCP286MB1897E2E996F847CF73C617D3A30A9@TYCP286MB1897.JPNP286.PROD.OUTLOOK.COM
(lines begin with '>>' are from my previous mail.)

Maxime Devos <maximedevos@telenet.be> writes:
Toggle quote (19 lines)
>> I made 'options' an sexp value since there are so many git options
>> (see 'man git-config').

> This can be solved with an escape hatch like openssh-configuration's
> 'extra-content' and by adding support for new options on an on-demand
> basis. If there are lots of options, that just means there's lot to
> do, I think.
> [...]
> Instead of this ad-hoc alist structure, how about introducing some
> structure with records, like done for other Guix services, e.g.
> 'openssh-configuration' and 'guix-configuration'?
> [...]
> To elaborate a little, I think the following options are the most
> important to support:

> user.name, user.email, commiter.name, committer.email
> smtp things (for git send-email, important for contributing to guix)
> pgp things (important for being a committer in guix)

Yes, add a proper record structure will make documentation and type
check more viable. I'll try later..


Toggle quote (8 lines)
>> I can also symlink the generated gitconfig into ~/.gitconfig, but
>> with 'GIT_CONFIG_SYSTEM' it can be used together with hand maintained
>> ~/.gitconfig.
> The GIT_CONFIG_SYSTEM is less stateful, I like it. There are multiple
> variables like these though: GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM and
> GIT_CONFIG. My guess is that GIT_CONFIG_GLOBAL would be appropriate
> here.

Set GIT_CONFIG_GLOBAL will shadow ~/.gitconfig, while GIT_CONFIG_SYSTEM
is applied before ~/.gitconfig, so that user can have some out-of guix
managed options in ~/.gitconfig if they really want (maybe password?).


Toggle quote (32 lines)
> ??? schreef op ma 07-03-2022 om 22:51 [+0800]:
>> Hello, with:
>> --8<---------------cut here---------------start------------->8---
>> (service home-git-service-type
>>  (home-git-configuration
>>   (options '((user (name "foo")
>>                    (email "foo@bar.com")))))) [...]
>
> How about providing an option for passwords? E.g.,
>
> (home-git-configuration
> (user (git-user-info
> (name "Foobar")
> (e-mail "Foobar <foo@bar.com>")
> (signing-key "some PGP fingerprint)))
> (secrets-file "/home/foo/the-password")
> (smtp (git-smtp-configuration
> #;(password "12345") ; not recommended, use 'secrets-file' instead
> ...))
>
> (with some appropriate documentation)
>
> secrets-file (not interned in the store):
>
> # I don't remember the exact option name
> smtp.password = Foobaz
>
> the produced .gitconfig would include a line
>
> [include]
> path = /home/foo/the-password

Um, I can get it with sexp options:
Toggle snippet (5 lines)
(options '((include (path "/home/foo/the-password"))
(include (path "/home/foo/another-file"))))


Or if with proper record fields, I'd like to keep the original git
variables names in scheme too:
Toggle snippet (7 lines)
(user.name "Foobar")
(user.email "foo@bar.com")
(include.path (list "/home/foo/the-password"
"/home/foo/another-file"))
(sendemail.smtpPass "12345" )

But with record field name, I don't know how to encode variables with
subsection (eg: url.<base>.insteadOf):



The subsection name may not be a valid scheme variable name...


I'll update this patch with adding doc and proper record fields for some
important options later, thank you!
I
I
iyzsong wrote on 12 Mar 2022 03:22
[PATCH v2] home: Add home-git-service-type.
(address . 54293@debbugs.gnu.org)(name . ???)(address . iyzsong@member.fsf.org)
TYCP286MB18973CA5D0DD1447744E30FAA30D9@TYCP286MB1897.JPNP286.PROD.OUTLOOK.COM
* gnu/home/services/git.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/home/services/git.scm | 214 ++++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
2 files changed, 215 insertions(+)
create mode 100644 gnu/home/services/git.scm

Toggle diff (234 lines)
diff --git a/gnu/home/services/git.scm b/gnu/home/services/git.scm
new file mode 100644
index 0000000000..f39c931c38
--- /dev/null
+++ b/gnu/home/services/git.scm
@@ -0,0 +1,214 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 ??? <iyzsong@member.fsf.org>
+;;;
+;;; 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 home services git)
+ #:use-module (gnu home services)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu packages version-control)
+ #:use-module (guix packages)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (ice-9 match)
+ #:export (home-git-service-type
+ home-git-configuration))
+
+(define (git-option-value? value)
+ (or (unspecified? value)
+ (string? value)
+ (integer? value)
+ (boolean? value)))
+
+(define (serialize-git-option-value value)
+ (cond
+ ((string? value) (with-output-to-string (lambda () (write value))))
+ ((integer? value) (number->string value))
+ ((boolean? value) (if value "true" "false"))))
+
+(define (git-options? options)
+ "Return #t if OPTIONS is a well-formed sexp for git options."
+ (define git-variable?
+ (match-lambda
+ ((key value) (and (symbol? key) (git-option-value? value)))
+ (_ #f)))
+ (every
+ (match-lambda
+ (((section subsection) variables ..1)
+ (and (symbol? section)
+ (string? subsection)
+ (every git-variable? variables)))
+ ((section variables ..1)
+ (and (symbol? section)
+ (every git-variable? variables)))
+ (_ #f))
+ options))
+
+(define (serialize-git-options options)
+ "Return the @command{git-config} text form for OPTIONS."
+ (define serialize-section
+ (match-lambda
+ ((section variables ..1)
+ (with-output-to-string
+ (lambda ()
+ (match section
+ ((section subsection)
+ (simple-format #t "[~a ~s]~%" section subsection))
+ (_
+ (simple-format #t "[~a]~%" section)))
+ (for-each
+ (match-lambda
+ ((key value)
+ (simple-format #t "\t~a = ~a~%"
+ key (serialize-git-option-value value))))
+ variables))))))
+ (string-concatenate (map serialize-section options)))
+
+(define-configuration/no-serialization home-git-configuration
+ (package
+ (package git)
+ "The Git package to use.")
+ (enable-send-email?
+ (boolean #t)
+ "Whether to install git email tools from the package's @code{send-email}
+output.")
+ (user.name
+ (git-option-value *unspecified*)
+ "The human-readable name used in the author and committer identity when
+creating commit or tag objects, or when writing reflogs. If you need the
+author or committer to be different, the @code{author.name} or
+@code{committer.name} can be set.")
+ (user.email
+ (git-option-value *unspecified*)
+ "The email address used in the author and committer identity when creating
+commit or tag objects, or when writing reflogs. If you need the author or
+committer to be different, the @code{author.email} or @code{committer.email}
+can be set.")
+ (user.signingKey
+ (git-option-value *unspecified*)
+ "If @command{git-tag} or @command{git-commit} is not selecting the key you
+want it to automatically when creating a signed tag or commit, you can
+override the default selection with this variable. This option is passed
+unchanged to gpg’s @code{--local-user} parameter, so you may specify a key
+using any method that gpg supports.")
+ (author.name
+ (git-option-value *unspecified*)
+ "The human-readable name used in the author identity when creating commit
+or tag objects, or when writing reflogs.")
+ (author.email
+ (git-option-value *unspecified*)
+ "The email address used in the author identity when creating commit or tag
+objects, or when writing reflogs.")
+ (committer.name
+ (git-option-value *unspecified*)
+ "The human-readable name used in the committer identity when creating
+commit or tag objects, or when writing reflogs.")
+ (committer.email
+ (git-option-value *unspecified*)
+ "The email address used in the author identity when creating commit or tag
+objects, or when writing reflogs.")
+ (commit.gpgSign
+ (git-option-value *unspecified*)
+ "A boolean to specify whether all commits should be GPG signed.")
+ (sendemail.smtpServer
+ (git-option-value *unspecified*)
+ "If set, specifies the outgoing SMTP server to
+use (e.g. @code{smtp.example.com} or a raw IP address). If unspecified, and if
+@var{sendemail.sendmailcmd} is also unspecified, the default is to search for
+@command{sendmail} in $PATH if such a program is available, falling back to
+@code{localhost} otherwise.")
+ (sendemail.smtpServerPort
+ (git-option-value *unspecified*)
+ "Specifies a port different from the default port (SMTP servers typically
+listen to smtp port 25, but may also listen to submission port 587, or the
+common SSL smtp port 465); symbolic port names (e.g. @code{submission} instead
+of 587) are also accepted.")
+ (sendemail.smtpUser
+ (git-option-value *unspecified*)
+ "Username for SMTP-AUTH. If a username is not specified, then
+authentication is not attempted.")
+ (sendemail.smtpPass
+ (git-option-value *unspecified*)
+ "Password for SMTP-AUTH. If not specified, then a password is obtained
+using @command{git-credential}.")
+ (sendemail.smtpEncryption
+ (git-option-value *unspecified*)
+ "Specify the encryption to use, either @code{ssl} or @code{tls}. Any other
+value reverts to plain SMTP.")
+ (sendemail.sendmailcmd
+ (git-option-value *unspecified*)
+ "Specify a command to run to send the email. The command should be
+sendmail-like; specifically, it must support the @code{-i} option. The
+command will be executed in the shell if necessary.")
+ (extra-options
+ (git-options '())
+ "Extra configuration options for Git."))
+
+(define (home-git-configuration-final-options config)
+ (let* ((fields
+ (filter
+ (lambda (field)
+ (eq? (configuration-field-type field) 'git-option-value))
+ home-git-configuration-fields))
+ (options
+ (filter
+ (match-lambda
+ ((section (key value)) (not (unspecified? value))))
+ (map (lambda (field)
+ (let* ((name (configuration-field-name field))
+ (section+key (map string->symbol
+ (string-split (symbol->string name) #\.)))
+ (value ((configuration-field-getter field) config)))
+ `(,(car section+key) (,(cadr section+key) ,value))))
+ fields)))
+ (extra-options (home-git-configuration-extra-options config))
+ (merge-options (lambda (options) ;merge options by section
+ (fold
+ (lambda (e prev)
+ (match e
+ ((section variables ..1)
+ (begin
+ (let ((v (assv-ref prev section)))
+ (assv-set! prev section
+ (if v (append v variables)
+ variables)))))))
+ '() options))))
+ (merge-options (append options extra-options))))
+
+(define (home-git-environment-variables config)
+ (let ((gitconfig (serialize-git-options
+ (home-git-configuration-final-options config))))
+ `(("GIT_CONFIG_SYSTEM" . ,(plain-file "gitconfig" gitconfig)))))
+
+(define (home-git-profile config)
+ (let ((package (home-git-configuration-package config)))
+ (if (home-git-configuration-enable-send-email? config)
+ `(,package (,package "send-email"))
+ `(,package))))
+
+(define home-git-service-type
+ (service-type (name 'home-git)
+ (extensions
+ (list (service-extension
+ home-environment-variables-service-type
+ home-git-environment-variables)
+ (service-extension
+ home-profile-service-type
+ home-git-profile)))
+ (default-value (home-git-configuration))
+ (description
+ "Install and configure the Git distributed revision control
+system.")))
diff --git a/gnu/local.mk b/gnu/local.mk
index 9bfeede60f..a5ea94b3a1 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -80,6 +80,7 @@ GNU_SYSTEM_MODULES = \
%D%/home.scm \
%D%/home/services.scm \
%D%/home/services/desktop.scm \
+ %D%/home/services/git.scm \
%D%/home/services/symlink-manager.scm \
%D%/home/services/fontutils.scm \
%D%/home/services/shells.scm \
--
2.34.0
M
M
Maxime Devos wrote on 12 Mar 2022 10:51
(name . ???)(address . iyzsong@member.fsf.org)
82375f0f494e3b729bf0ed0fa3a55bede0a18ae5.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (4 lines)
> +(define (serialize-git-option-value value)
> +  (cond
> +   ((string? value) (with-output-to-string (lambda () (write value))))

Does git follow the same escaping rules as Guile?

Toggle quote (3 lines)
> +   ((integer? value) (number->string value))
> +   ((boolean? value) (if value "true" "false"))))

This (and more generally, the home-git-service-type) needs to be
documented in the manual.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixtHhccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7q7MAQC3sqVp5mEPqQcxNFPKEMTK5ILF
uLWTz1sg34theVrQVAD/SR2ivaFli73G71CMOYjj8Mwzf7sVVE7DHAmT/69S5w4=
=dJih
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 10:54
(name . ???)(address . iyzsong@member.fsf.org)
ff9bfdb70d653047dcd564164fca568417a9d120.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (3 lines)
> + (user.name
> +   (git-option-value *unspecified*))

I think *unspecified* is considered an implementation detail. Proposal:
let it be #false by default, and don't serialize the option whenever it
is #false.

Also, I don't think that user names can be #false, #true or integers.
Perhaps a 'git-string-value' would be useful?

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixtxxccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7lGHAP4hdXaCnEubbeJPwdBdr7IeUI+X
80NFepC5/9cnn2eARAD/b9zaz/NB84SAaNjmsJRM37QoewPQPpUf8yZaCwk6xAE=
=tvCJ
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 10:58
(name . ???)(address . iyzsong@member.fsf.org)
69025df84189c9ba933d32dd39d6f092c76b3fc4.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (7 lines)
> +  (user.email [...])
> +  (user.signingKey [...])
> +  (author.name [...])
> +  (author.email [...])
> +  (committer.name [...])
> +  (committer.email [...])

Conventionally (Guile) Scheme symbols are lowercase and don't use dots.
I suppose you could do 'user-signing-key'.

However, there seems to be quite some duplication between 'user',
'author' and 'committer'. Perhaps you could abstract things a little
by e.g. doing something like the git-user-info record I proposed?

(home-git-configuration
(user (git-user-info (name ...) (e-mail ...) (signing-key ...))
(author user)
(committer user)
[other options])

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iIwEABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixuuRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7uYsAQD9sOmivz8M4/WeuGd5vhg5ff8K
O9JzkI0Pda2eRcNL3QD3bGfMkmNm4J/mjuDKFoYKMgB4udI1dIHTnzNF0G2WDg==
=lJ6p
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:02
(name . ???)(address . iyzsong@member.fsf.org)
603cf5d762cebe92c15a9b50a8df121d97bf2e68.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (6 lines)
> +(define (home-git-profile config)
> +  (let ((package (home-git-configuration-package config)))
> +    (if (home-git-configuration-enable-send-email? config)
> +        `(,package (,package "send-email"))
> +        `(,package))))

Why is git added to the profile?

E.g., what if, say, I want to use "guix home" only for setting up
environment variables, dot files, etc, but not for installing software,
and I want to use "guix install" for installing software?

Alternatively, what if most of the time I don't use Guix, so I have no
need for "git" in the environment, and when I do need git, I'll just do
"guix shell git" to temporarily add it?

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixvmBccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7ld/AQCHiDerPVcXe04uFplQXdIeQIFD
R6qUndmH8akDBNCztAEAjO0+D4ZvnCRnYdOhRgW8Y5iMibPo3WwFSYXueJXPzgQ=
=HdmW
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:03
(name . ???)(address . iyzsong@member.fsf.org)
6be8d3ea9366c82981a3cd39d20e5d8dcf73eb17.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (3 lines)
> +   "Whether to install git email tools from the package's @code{send-email}
> +output.")

Perhaps add a little text about benefits/downsides?
E.g.,

"Enabling this allows sending patch e-mails from git with @code{git
send-email}, at the cost of an increase in closure size."

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixv8RccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7mTeAP9dINIOwWlwYlrvzv93JaRrvqZF
C+b7/Q9a0yXDhrQqSQD9F3aLXboMWo00ULPUN3+4ApRNJV9A91cPwBsAeCV6QwI=
=+Xnh
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:11
(name . ???)(address . iyzsong@member.fsf.org)
51a5aff9fb6644a1c8cf8d22ef55a5f84a613385.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (5 lines)
> +   "The human-readable name used in the author and committer identity when
> +creating commit or tag objects, or when writing reflogs.  If you need the
> +author or committer to be different, the @code{author.name} or
> +@code{committer.name} can be set.")

It does not need to he human-readable AFAIK, space aliens could write a
name in some space alphabet not understood by humans here (as long as
it's in Unicode).

This sentence could be simplified a lot:

"The name of the committer and author to record in commits and tags.
By default, git assumes the committer and author name to be the same.
To override this, the field @code{author.name} or @code{committer.name}
can be set."

This technically ignores reflogs, but I expect most people using git to
not have to know what reflogs are.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixxzRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7jKBAPsET2U9Ucto54NcsHYxn5kW9U2H
zjuD9NdgVhQqU2jnCgD9FgOfKKxXC5ORMfiiLUtvcgVEy5fOYUa3xzlCWqtNnQs=
=+NzL
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:12
(name . ???)(address . iyzsong@member.fsf.org)
270a0a2231b7e5d81d041455bf5af0b4bca7ffcd.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (2 lines)
> +   "If @command{git-tag} or @command{git-commit}

I don't have a 'git-tag' or 'git-commit', but I do have 'git tag' and
'git commit'. What are the hyphen-minuses doing here?

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYixyGxccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7g54AP0d9D0kOMyU3iwwbSXYf7zqIx9G
csEGd/U9l/5anc4oNQD9HZR4rlOtiaUjXEksr2XRgCe1PP8+Q8TFPVGarMrC9gU=
=tUVP
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:21
(name . ???)(address . iyzsong@member.fsf.org)
dc029ae7c6b3f7fa26d663194d50f06c6c4ced92.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (6 lines)
> +   "If @command{git-tag} or @command{git-commit} is not selecting the key you
> +want it to automatically when creating a signed tag or commit, you can
> +override the default selection with this variable.  This option is passed
> +unchanged to gpg’s @code{--local-user} parameter, so you may specify a key
> +using any method that gpg supports.")

I would do this in the third person (I think the manual recommends this
somewhere but I wouldn't know where), and avoid mentioning the
implementation details (‘this option is passed to’) in favour of the
meaning (basically, ‘declarative’ documentation instead of ‘procedural’
documentation).

Proposal:

"The PGP key, if any, to sign commmits and tags with. This can be in
any format that gpg's @code{--local-user} parameter support, e.g. a PGP
fingerprint or an e-mail (*) address. If set to @code{#false}, this
defaults to a private key corresponding to the name and e-mail of the
committer."

(*) I don't know if Guix uses "email" or "e-mail".

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYix0PRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7uvJAP0Ujh+Ka/TBJcr7LVqdND10IqH6
UqpzGjb0i3Rh8ls9EQEA/9GoaGrnY5RPejvQ/cJ745se9WVXIiMuj2BpYeYcbwM=
=Ggj7
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:24
(name . ???)(address . iyzsong@member.fsf.org)
ea5cdfc7d1c278af2c693ce1ba446e4eacd2dbb5.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (12 lines)
> +         (merge-options (lambda (options) ;merge options by section
> +                          (fold
> +                           (lambda (e prev)
> +                             (match e
> +                               ((section variables ..1)
> +                                (begin
> +                                  (let ((v (assv-ref prev section)))
> +                                   (assv-set! prev section
> +                                              (if v (append v variables)
> +                                                  variables)))))))
> +                           '() options))))

Seems rather imperative. Can this be avoided, e.g. using vhashes?
Excerpt from the manual:

Toggle quote (7 lines)
> 18.5.1 Programming Paradigm
> ---------------------------
>
> Scheme code in Guix is written in a purely functional style. One
> exception is code that involves input/output, and procedures that
> implement low-level concepts, such as the ‘memoize’ procedure.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYix09BccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7qvcAP9jQzsvBL63vitrwGMGsvC4Uk5r
2rWViUmdTlrcEH2P1wEA7kgjHUY2A0hVnaFzn3EXknWJ0vI5ahOxe3eSkQDAwgk=
=bfzp
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:26
(name . ???)(address . iyzsong@member.fsf.org)
4e1d4b59b1ceae89aeb0f66268cec966a4a98476.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (3 lines)
> +   "Specify the encryption to use, either @code{ssl} or @code{tls}.  Any other
> +value reverts to plain SMTP.")

This seems easy to go wrong, e.g. what if I accidentally pass a value
in uppercase, e.g. "SSL" or "TLS"? I recommend validating this value
instead of silently not encrypting.

Also, does this need to be a symbol, or a string? Looking at the
documentation, I would expect a symbol, but looking at the
implementation, it seems to have to be a string.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYix1cRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7iu2AQDeKjqL6ZcYcRnojboFXsaQXzZ5
szKAYO+6HiUeVPoH6QEA1EYhzmiXrvQMIciplG/gNgHJLijJ0U+/nUtEyD3GKw4=
=vY5V
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:31
(name . ???)(address . iyzsong@member.fsf.org)
a325329ae24a0d1f0e82c3104bb48018bc78c40a.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (3 lines)
> +  (commit.gpgSign
> +   (git-option-value *unspecified*)

Would be nice to validate it's a boolean, and not, say, a string or
number.

Toggle quote (2 lines)
> +   "A boolean to specify whether all commits should be GPG signed.")

I'm wondering, should 'gpg.program' be set instead of relying on $PATH?

Also, this can be overriden with "-S", so perhaps

"A boolean specifying whether to sign commits by default, with
OpenPGP."

Also, the exact implementation (GPG) of OpenPGP used seems an
implementation detail, hence my suggestion GPG->OpenPGP.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYix2jxccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7qk6AQCiQ/5aVa6P/wzuGjmmcyHwex0o
HTOMX7o+vNhu2qJE9AEAs1C/Hyv/8qbvy74ehZ7XDv0ab6zquPdCiGoPrIEfPgo=
=Ypip
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 11:39
(name . ???)(address . iyzsong@member.fsf.org)
7f91ab84150dca8bf9a4ea24e08bc05ff75fccc4.camel@telenet.be
iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
Toggle quote (3 lines)
> +   "If set, specifies the outgoing SMTP server to
> +use (e.g. @code{smtp.example.com} or a raw IP address).

How does smtp.example.com specify the SMTP server? As a DNS address?

Does that mean I can do

(sendemail.smtpServer
(make-socket-address AF_INET INADDR_LOOPBACK some-number ...))?

'make-socket-address' is Guile's procedure for making an address,
'AF_INET' indicates IP is used, INADDR_LOOPBACK some-number indicates
which IP address ...

Also, wouldn't a raw IP address be a 32-bit integer? (or 128-bit in
case of IPv6)? And in case of IPv6, is this with or without
surrounding [brackets]? Perhaps a reference to the relevant Internet
RFC would be useful.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYix4aRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7u3cAP9P42sY/WoF0dhC3IanDsOtUCQY
b2QfKayL+jlElqWMeAEAvKHa9TGxvAKW+t4UI3V3TMOHcZX5chuSUXWzYwUOFgk=
=AsBK
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 12 Mar 2022 23:27
Re: [bug#54293] [WIP] home: Add home-git-service-type
(name . ???)(address . iyzsong@outlook.com)(address . 54293@debbugs.gnu.org)
1c1da14a956cfb91aec74cba0440d43c8e1048a4.camel@telenet.be
??? schreef op wo 09-03-2022 om 20:50 [+0800]: [...]

I didn't notice this mail (and the other) before sending replies on the
v2, apologies! They ended up in spam somehow. I'll try to look into
them later ...

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYi0ePRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7jHkAQCWctGYORuonTx7EJ+xwwjG+Zwg
kNQHvG0luFOitVur3AEA2ktXIK4XUiBgcEEPIsMBQP7C6bRl7yQFMsrJo4IOXAc=
=xvu1
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 29 Mar 2022 15:56
Re: bug#54293: [WIP] home: Add home-git-service-type
(name . Maxime Devos)(address . maximedevos@telenet.be)
87zgl8x3p2.fsf_-_@gnu.org
Maxime Devos <maximedevos@telenet.be> skribis:

Toggle quote (6 lines)
> iyzsong@outlook.com schreef op za 12-03-2022 om 10:22 [+0800]:
>> + (user.name
>> +   (git-option-value *unspecified*))
>
> I think *unspecified* is considered an implementation detail.

Yes, but it may be useful to be able to distinguish between “not
specified” and “false”.

To do that you can either use ‘*unspecified*’ or some other unique
value that you’d compare with ‘eq?’, say:

(define &not-specified (list 'not 'specified))
(define (specified? value)
(not (eq? value &not-specified)))

But really, ‘*unspecified*’ is okay IMO.

Ludo’.
L
L
Ludovic Courtès wrote on 21 May 2022 15:47
(address . iyzsong@outlook.com)
878rqvuhew.fsf_-_@gnu.org
Hi ???,

iyzsong@outlook.com skribis:

Toggle quote (3 lines)
> * gnu/home/services/git.scm: New file.
> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it.

It’s been a while already but I think it’d be a nice addition. I think
Maxime raised good points while reviewing, in particular regarding
naming conventions (lowercase and without dots) and possible grouping
(all the ‘user.’ options might fit in a single <git-user> record or
similar?).

How do you feel about making hopefully final changes so you can push it?

Thanks in advance! :-)

Ludo’.
?