diff mbox series

[bug#54293,WIP] home: Add home-git-service-type

Message ID TYCP286MB189799FE00EC37FC1D454CA2A3089@TYCP286MB1897.JPNP286.PROD.OUTLOOK.COM
State New
Headers show
Series [bug#54293,WIP] home: Add home-git-service-type | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue

Commit Message

宋文武 March 7, 2022, 2:51 p.m. UTC
Hello, with:
--8<---------------cut here---------------start------------->8---
(service home-git-service-type
 (home-git-configuration
  (options '((user (name "foo")
                   (email "foo@bar.com"))))))
--8<---------------cut here---------------end--------------->8---

We'll have git in the home profile, and GIT_CONFIG_SYSTEM pointing to a
file contains:
--8<---------------cut here---------------start------------->8---
[user]
	name = "foo"
	email = "foo@bar.com"
--8<---------------cut here---------------end--------------->8---

Which set the system-level options for git.
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 :)

Comments

M March 7, 2022, 5:58 p.m. UTC | #1
宋文武 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.

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.
M March 7, 2022, 6:01 p.m. UTC | #2
宋文武 schreef op ma 07-03-2022 om 22:51 [+0800]:
> +  (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.
M March 7, 2022, 6:02 p.m. UTC | #3
宋文武 schreef op ma 07-03-2022 om 22:51 [+0800]:
> 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.
M March 7, 2022, 6:04 p.m. UTC | #4
宋文武 schreef op ma 07-03-2022 om 22:51 [+0800]:
> 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.
M March 7, 2022, 6:11 p.m. UTC | #5
宋文武 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
M March 7, 2022, 6:12 p.m. UTC | #6
Maxime Devos schreef op ma 07-03-2022 om 19:01 [+0100]:
> 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.
宋文武 March 9, 2022, 12:18 p.m. UTC | #7
Maxime Devos <maximedevos@telenet.be> writes:

> 宋文武 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.

>
> 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!
宋文武 March 9, 2022, 12:50 p.m. UTC | #8
(lines begin with '>>' are from my previous mail.)

Maxime Devos <maximedevos@telenet.be> writes:
>> 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..


>> 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?).


> 宋文武 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:
--8<---------------cut here---------------start------------->8---
  (options '((include (path "/home/foo/the-password"))
             (include (path "/home/foo/another-file"))))
--8<---------------cut here---------------end--------------->8---


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

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

  [url "https://mirror.sjtu.edu.cn/git/guix.git"]
    insteadof = https://git.savannah.gnu.org/git/guix.git


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!
M March 12, 2022, 10:27 p.m. UTC | #9
宋文武 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.
diff mbox series

Patch

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

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