From d44b9efda2d387430e63c1d6cd426c88bcde2eda Mon Sep 17 00:00:00 2001 From: Timo Wilken Date: Tue, 12 Sep 2023 19:42:21 +0200 Subject: Factor out proper Git and GnuPG service types --- tw/services/git.scm | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++ tw/services/gnupg.scm | 94 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 tw/services/git.scm create mode 100644 tw/services/gnupg.scm (limited to 'tw/services') diff --git a/tw/services/git.scm b/tw/services/git.scm new file mode 100644 index 00000000..69dae1e8 --- /dev/null +++ b/tw/services/git.scm @@ -0,0 +1,108 @@ +(define-module (tw services git) + #:use-module (gnu) + #:use-module (gnu home services) + #:use-module (gnu packages terminals) + #:use-module (gnu packages version-control) + #:use-module (gnu services configuration) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module ((guix records) #:select (match-record)) + #:use-module (srfi srfi-1) + #:export (home-git-identity + home-git-configuration + home-git-service-type)) + +(define-configuration/no-serialization home-git-identity + (name string "Short slug identifying this identity. Only used to name config files.") + (root-directory string "Directory under which this identity should apply.") + (email string "Author commits as this email for this identity.") + (signing-key string "Sign commits using this key for this identity.")) + +(define (list-of-identities? thing) + (and (list? thing) (every home-git-identity? thing))) + +(define-configuration/no-serialization home-git-configuration + (default-email string "Author git commits as this email.") + (default-signing-key string "Sign git commits using this email.") + (identities (list-of-identities '()) "Override default configuration values +under specific directories, e.g. to use a work identity in a directory +containing work projects.")) + +(define (gitconfig-includes identities) + (if (null? identities) '() + (cons (match-record (car identities) + (name root-directory) + ;; A relative path is relative to the gitconfig file. + (format #f "[includeIf \"gitdir:~a/**\"]\n\tpath = ~aconfig" + (string-trim-right root-directory #\/) name)) + (gitconfig-includes (cdr identities))))) + +(define (gitconfig-otherfiles identities) + (if (null? identities) '() + (cons (match-record (car identities) + (name email signing-key) + (list + (string-append "git/" name "config") + (plain-file (string-append "git" name "config") + (string-append + "[user]\n" + (if email (string-append "\temail = " email "\n") "") + (if signing-key (string-append "\tsigningkey = " signing-key "\n") ""))))) + (gitconfig-otherfiles (cdr identities))))) + +(define (gitconfig config) + (match-record config + (default-email default-signing-key identities) + `(,@(gitconfig-otherfiles identities) + ("git/config" ,(mixed-text-file "gitconfig" "\ +# This is Git's per-user configuration file. +[user] + name = Timo Wilken + email = " default-email " + signingkey = " default-signing-key + (string-join (gitconfig-includes identities) "\n" 'prefix) " +[commit] + gpgsign = true +[url \"ssh://git@gitlab.cern.ch:7999/\"] + insteadOf = https://gitlab.cern.ch/ +[url \"ssh://git@ssh.github.com/\"] + insteadOf = gh: +[gui] + fontui = -family \\\"Fira Sans\\\" -size 10 -weight normal -slant roman -underline 0 -overstrike 0 + fontdiff = -family \\\"Hermit\\\" -size 10 -weight normal -slant roman -underline 0 -overstrike 0 + tabsize = 4 +[merge] + summary = true + conflictstyle = diff3 +[color] + ui = auto +[pull] + rebase = false + ff = only +[alias] + glog = log --decorate --graph --oneline + plog = log --decorate --graph --oneline --pretty=tformat:\\\"%C(yellow)%h %Cgreen%as %Cblue%<(10,trunc)%an%Cred%d%Creset %s\\\" +[init] + defaultBranch = master +[advice] + detachedHead = false + addEmptyPathspec = false +# https://sw.kovidgoyal.net/kitty/kittens/diff/ +[diff] + tool = kitty + guitool = kitty.gui +[difftool] + prompt = false + trustExitCode = true +[difftool \"kitty\"] + cmd = " kitty "/bin/kitty +kitten diff $LOCAL $REMOTE +[difftool \"kitty.gui\"] + cmd = " kitty "/bin/kitty " kitty "/bin/kitty +kitten diff $LOCAL $REMOTE +"))))) + +(define home-git-service-type + (service-type + (name 'git) + (extensions + (list (service-extension home-xdg-configuration-files-service-type gitconfig))) + (description "Configure Git."))) diff --git a/tw/services/gnupg.scm b/tw/services/gnupg.scm new file mode 100644 index 00000000..9b358ea4 --- /dev/null +++ b/tw/services/gnupg.scm @@ -0,0 +1,94 @@ +(define-module (tw services gnupg) + #:use-module (gnu) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:use-module (gnu packages gnupg) + #:use-module ((gnu packages image-viewers) + #:select (imv)) + #:use-module (gnu services configuration) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module ((guix records) #:select (match-record)) + #:export (home-gnupg-configuration + home-gnupg-service-type)) + +(define-configuration/no-serialization home-gnupg-configuration + (default-key string "The user's own key. Always encrypt to this key, and +use it by default.") + (gui-pinentry? boolean "Use pinentry-rofi if true, else pinentry-tty.") + (keyserver (string "hkps://keys.openpgp.org") "The default keyserver to use.") + (gnupg (package gnupg) "The GnuPG package to use.") + (image-viewer (file-like (file-append imv "/bin/imv")) "A gexp returning a +string, specifying the command to call in order to view images.") + (gnupghome (string "$XDG_DATA_HOME/gnupg") "The value of $GNUPGHOME in the +environment.")) + +(define (gnupg-xdg config) + `(("GNUPGHOME" . ,(home-gnupg-configuration-gnupghome config)))) + +(define (gnupg-files config) + (match-record config + (default-key gui-pinentry? keyserver image-viewer) + `(;; GnuPG config files must be in ~/.local/share/gnupg, not ~/.config, + ;; so we can't use `home-xdg-configuration-files-service-type'. + (".local/share/gnupg/dirmngr.conf" + ,(mixed-text-file "dirmngr.conf" + "keyserver " keyserver "\n")) + (".local/share/gnupg/gpg.conf" + ,(mixed-text-file "gpg.conf" "\ +# This options file can contain any long options to GnuPG. +# See the gpg man page for a list of options. +# Comments can only be at the start of a line, not after options. + +default-key " default-key " +default-recipient-self +use-agent +# Get rid of the copyright notice. +no-greeting +# Always encrypt to my key as well, in addition to any recipient. +encrypt-to " default-key " +auto-key-import +auto-key-retrieve +photo-viewer \"" image-viewer " %i\" + +# Because some mailers change lines starting with 'From ' to '>From ' +# it is good to handle such lines in a special way when creating +# cleartext signatures; all other PGP versions do it this way too. +# To enable full OpenPGP compliance you may want to use this option. +#no-escape-from-lines +")) + (".local/share/gnupg/gpg-agent.conf" + ,(mixed-text-file "gpg-agent.conf" "\ +pinentry-program " (if gui-pinentry? + (file-append pinentry-rofi "/bin/pinentry-rofi") + (file-append pinentry-tty "/bin/pinentry-tty")) " +# Keep passphrase cached for longer, so that mcron jobs (e.g. restic, +# vdirsyncer) can access the password store. Vdirsyncer should run every half +# hour to extend the default-cache-ttl. +default-cache-ttl 2100 # 35 min +max-cache-ttl 43200 # 12 h +# Needed if spawning lots of parallel gpg --decrypt processes. https://dev.gnupg.org/T3530 +auto-expand-secmem +"))))) + +(define (gnupg-shepherd config) + (match-record config (gnupg) + (list (shepherd-service + (documentation "GPG agent; caches key passwords.") + (provision '(gpg-agent)) + (start #~(lambda _ + (invoke #$(file-append gnupg "/bin/gpg-agent") + "--daemon" "--no-detach"))) + (stop #~(lambda _ + (invoke #$(file-append gnupg "/bin/gpg-connect-agent") + "killagent" "/bye"))))))) + +(define home-gnupg-service-type + (service-type + (name 'gnupg) + (extensions + (list (service-extension home-shepherd-service-type gnupg-shepherd) + (service-extension home-files-service-type gnupg-files) + (service-extension home-environment-variables-service-type gnupg-xdg))) + (description + "Install GnuPG configuration files and run the agent."))) -- cgit v1.2.3