Files
lux/modules/features/source-control.nix
T
2026-04-25 00:19:20 +02:00

109 lines
2.9 KiB
Nix

{ config, lib, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager.source-control =
{
config,
lib,
...
}:
let
machine = config.meta.machine;
user = config.meta.user;
account = user.account;
sourceControl = account.sourceControl;
scopeConfig = scope: user.sourceControl.${scope} or null;
emailForScope =
scope:
let
scopedEmails = lib.filter (email: email.scope == scope) (builtins.attrValues account.emails);
in
if builtins.length scopedEmails == 1 then (builtins.head scopedEmails).address else 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
];
missingEmailScopes = 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 = account.realName;
email = emailForScope scope;
};
}
(
lib.optionalAttrs (scopeHasSigningKey scope) {
gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
user.signingKey = "${privateKeyPathForScope scope}.pub";
}
);
gitRoots = [
{
root = account.nixosConfigurationPath;
scope = "personal";
}
{
root = config.xdg.userDirs.projects;
scope = sourceControl.projectScope;
}
];
in
{
imports = [ homeModules.git ];
assertions = [
{
assertion = missingEmailScopes == [ ];
message = "Missing source-control email scope for `${account.name}`: ${lib.concatStringsSep ", " missingEmailScopes}.";
}
];
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" (
allowedSignersLines ++ [ "" ]
);
programs.git.includes = map (gitRoot: {
condition = "gitdir:${gitRoot.root}/";
contents = gitConfigForScope gitRoot.scope;
}) gitRoots;
};
}