{ config, lib, ... }: let homeModules = config.flake.modules.homeManager; in { flake.modules.homeManager.source-control = { config, lib, ... }: let host = config.meta.host; user = config.meta.user; sourceControl = user.sourceControl; hostSourceControlUsers = host.sourceControl.users; hostUserSourceControl = hostSourceControlUsers.${user.name} or { }; scopeEmails = scope: lib.filter (email: email.scope == scope) (builtins.attrValues user.emails); emailForScope = scope: let emails = scopeEmails scope; in if builtins.length emails == 1 then (builtins.head emails).address else null; scopeConfig = scope: hostUserSourceControl.${scope} or null; scopeHasSigningKey = scope: let keyConfig = scopeConfig scope; in keyConfig != null && keyConfig.publicKey != null; privateKeyPathForScope = scope: let keyConfig = scopeConfig scope; in if keyConfig == null || keyConfig.privateKeyPath == null then "~/.ssh/id_${scope}" else keyConfig.privateKeyPath; publicKeyForScope = scope: let keyConfig = scopeConfig scope; in if keyConfig == null then null else keyConfig.publicKey; scopesInUse = lib.unique ( [ "personal" sourceControl.projectScope ] ); invalidEmailScopes = builtins.filter (scope: emailForScope scope == null) scopesInUse; allowedSignersLines = map (scope: "${emailForScope scope} ${publicKeyForScope scope}") ( builtins.filter (scope: emailForScope scope != null && scopeHasSigningKey scope) scopesInUse ); gitConfigForScope = scope: lib.recursiveUpdate { user = { name = user.realName; email = emailForScope scope; }; } (lib.optionalAttrs (scopeHasSigningKey scope) { gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers"; user.signingKey = "${privateKeyPathForScope scope}.pub"; }); gitRoots = [ { root = user.nixosConfigurationPath; scope = "personal"; } { root = config.xdg.userDirs.projects; scope = sourceControl.projectScope; } ]; in { imports = [ homeModules.git ]; assertions = [ { assertion = invalidEmailScopes == [ ]; message = "Expected exactly one scoped email for `${user.name}` source-control scopes: ${lib.concatStringsSep ", " invalidEmailScopes}."; } ]; xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" ( allowedSignersLines ++ [ "" ] ); programs.git.includes = map (gitRoot: { condition = "gitdir:${gitRoot.root}/"; contents = gitConfigForScope gitRoot.scope; }) gitRoots; }; }