treewide: implement auto importing for modules
Reduce maintenance burden and increase efficiency by automatically importing modules following a specific convention. Co-authored-by: awwpotato <awwpotato@voidq.com> Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
This commit is contained in:
parent
fefeb0e928
commit
4fca600cb1
461 changed files with 72 additions and 474 deletions
936
modules/programs/git/default.nix
Normal file
936
modules/programs/git/default.nix
Normal file
|
|
@ -0,0 +1,936 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
literalExpression
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkOptionDefault
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.programs.git;
|
||||
|
||||
gitIniType =
|
||||
with types;
|
||||
let
|
||||
primitiveType = either str (either bool int);
|
||||
multipleType = either primitiveType (listOf primitiveType);
|
||||
sectionType = attrsOf multipleType;
|
||||
supersectionType = attrsOf (either multipleType sectionType);
|
||||
in
|
||||
attrsOf supersectionType;
|
||||
|
||||
includeModule = types.submodule (
|
||||
{ config, ... }:
|
||||
{
|
||||
options = {
|
||||
condition = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Include this configuration only when {var}`condition`
|
||||
matches. Allowed conditions are described in
|
||||
{manpage}`git-config(1)`.
|
||||
'';
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = with types; either str path;
|
||||
description = "Path of the configuration file to include.";
|
||||
};
|
||||
|
||||
contents = mkOption {
|
||||
type = types.attrsOf types.anything;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
user = {
|
||||
email = "bob@work.example.com";
|
||||
name = "Bob Work";
|
||||
signingKey = "1A2B3C4D5E6F7G8H";
|
||||
};
|
||||
commit = {
|
||||
gpgSign = true;
|
||||
};
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Configuration to include. If empty then a path must be given.
|
||||
|
||||
This follows the configuration structure as described in
|
||||
{manpage}`git-config(1)`.
|
||||
'';
|
||||
};
|
||||
|
||||
contentSuffix = mkOption {
|
||||
type = types.str;
|
||||
default = "gitconfig";
|
||||
description = ''
|
||||
Nix store name for the git configuration text file,
|
||||
when generating the configuration text from nix options.
|
||||
'';
|
||||
|
||||
};
|
||||
};
|
||||
config.path = mkIf (config.contents != { }) (
|
||||
mkDefault (
|
||||
pkgs.writeText (lib.hm.strings.storeFileName config.contentSuffix) (
|
||||
lib.generators.toGitINI config.contents
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
khaneliman
|
||||
rycee
|
||||
];
|
||||
|
||||
options = {
|
||||
programs.git = {
|
||||
enable = mkEnableOption "Git";
|
||||
|
||||
package = lib.mkPackageOption pkgs "git" {
|
||||
example = "pkgs.gitFull";
|
||||
extraDescription = ''
|
||||
Use {var}`pkgs.gitFull`
|
||||
to gain access to {command}`git send-email` for instance.
|
||||
'';
|
||||
};
|
||||
|
||||
userName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Default user name to use.";
|
||||
};
|
||||
|
||||
userEmail = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Default user email to use.";
|
||||
};
|
||||
|
||||
aliases = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
example = {
|
||||
co = "checkout";
|
||||
};
|
||||
description = "Git aliases to define.";
|
||||
};
|
||||
|
||||
signing = {
|
||||
key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The default signing key fingerprint.
|
||||
|
||||
Set to `null` to let the signer decide what signing key
|
||||
to use depending on commit’s author.
|
||||
'';
|
||||
};
|
||||
|
||||
format = mkOption {
|
||||
type = types.nullOr (
|
||||
types.enum [
|
||||
"openpgp"
|
||||
"ssh"
|
||||
"x509"
|
||||
]
|
||||
);
|
||||
defaultText = literalExpression ''
|
||||
"openpgp" for state version < 25.05,
|
||||
undefined for state version ≥ 25.05
|
||||
'';
|
||||
description = ''
|
||||
The signing method to use when signing commits and tags.
|
||||
Valid values are `openpgp` (OpenPGP/GnuPG), `ssh` (SSH), and `x509` (X.509 certificates).
|
||||
'';
|
||||
};
|
||||
|
||||
signByDefault = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = "Whether commits and tags should be signed by default.";
|
||||
};
|
||||
|
||||
signer = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "Path to signer binary to use.";
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.either types.lines gitIniType;
|
||||
default = { };
|
||||
example = {
|
||||
core = {
|
||||
whitespace = "trailing-space,space-before-tab";
|
||||
};
|
||||
url."ssh://git@host".insteadOf = "otherhost";
|
||||
};
|
||||
description = ''
|
||||
Additional configuration to add. The use of string values is
|
||||
deprecated and will be removed in the future.
|
||||
'';
|
||||
};
|
||||
|
||||
hooks = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
pre-commit = ./pre-commit-script;
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Configuration helper for Git hooks.
|
||||
See <https://git-scm.com/docs/githooks>
|
||||
for reference.
|
||||
'';
|
||||
};
|
||||
|
||||
iniContent = mkOption {
|
||||
type = gitIniType;
|
||||
internal = true;
|
||||
};
|
||||
|
||||
ignores = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"*~"
|
||||
"*.swp"
|
||||
];
|
||||
description = "List of paths that should be globally ignored.";
|
||||
};
|
||||
|
||||
attributes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "*.pdf diff=pdf" ];
|
||||
description = "List of defining attributes set globally.";
|
||||
};
|
||||
|
||||
includes = mkOption {
|
||||
type = types.listOf includeModule;
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[
|
||||
{ path = "~/path/to/config.inc"; }
|
||||
{
|
||||
path = "~/path/to/conditional.inc";
|
||||
condition = "gitdir:~/src/dir";
|
||||
}
|
||||
]
|
||||
'';
|
||||
description = "List of configuration files to include.";
|
||||
};
|
||||
|
||||
lfs = {
|
||||
enable = mkEnableOption "Git Large File Storage";
|
||||
|
||||
skipSmudge = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Skip automatic downloading of objects on clone or pull.
|
||||
This requires a manual {command}`git lfs pull`
|
||||
every time a new commit is checked out on your repository.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
maintenance = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Enable the automatic {command}`git maintenance`.
|
||||
|
||||
If you have SSH remotes, set {option}`programs.git.package` to a
|
||||
git version with SSH support (eg: `pkgs.gitFull`).
|
||||
|
||||
See <https://git-scm.com/docs/git-maintenance>.
|
||||
'';
|
||||
};
|
||||
|
||||
repositories = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Repositories on which {command}`git maintenance` should run.
|
||||
|
||||
Should be a list of absolute paths.
|
||||
'';
|
||||
};
|
||||
|
||||
timers = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {
|
||||
hourly = "*-*-* 1..23:53:00";
|
||||
daily = "Tue..Sun *-*-* 0:53:00";
|
||||
weekly = "Mon 0:53:00";
|
||||
};
|
||||
description = ''
|
||||
Systemd timers to create for scheduled {command}`git maintenance`.
|
||||
|
||||
Key is passed to `--schedule` argument in {command}`git maintenance run`
|
||||
and value is passed to `Timer.OnCalendar` in `systemd.user.timers`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
diff-highlight = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Enable the contrib {command}`diff-highlight` syntax highlighter.
|
||||
See <https://github.com/git/git/blob/master/contrib/diff-highlight/README>,
|
||||
'';
|
||||
};
|
||||
|
||||
pagerOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"--tabs=4"
|
||||
"-RFX"
|
||||
];
|
||||
description = ''
|
||||
Arguments to be passed to {command}`less`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
difftastic = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Enable the {command}`difftastic` syntax highlighter.
|
||||
See <https://github.com/Wilfred/difftastic>.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "difftastic" { };
|
||||
|
||||
enableAsDifftool = mkEnableOption "" // {
|
||||
description = ''
|
||||
Enable the {command}`difftastic` syntax highlighter as a git difftool.
|
||||
See <https://github.com/Wilfred/difftastic>.
|
||||
'';
|
||||
};
|
||||
|
||||
background = mkOption {
|
||||
type = types.enum [
|
||||
"light"
|
||||
"dark"
|
||||
];
|
||||
default = "light";
|
||||
example = "dark";
|
||||
description = ''
|
||||
Determines whether difftastic should use the lighter or darker colors
|
||||
for syntax highlighting.
|
||||
'';
|
||||
};
|
||||
|
||||
color = mkOption {
|
||||
type = types.enum [
|
||||
"always"
|
||||
"auto"
|
||||
"never"
|
||||
];
|
||||
default = "auto";
|
||||
example = "always";
|
||||
description = ''
|
||||
Determines when difftastic should color its output.
|
||||
'';
|
||||
};
|
||||
|
||||
display = mkOption {
|
||||
type = types.enum [
|
||||
"side-by-side"
|
||||
"side-by-side-show-both"
|
||||
"inline"
|
||||
];
|
||||
default = "side-by-side";
|
||||
example = "inline";
|
||||
description = ''
|
||||
Determines how the output displays - in one column or two columns.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
delta = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Whether to enable the {command}`delta` syntax highlighter.
|
||||
See <https://github.com/dandavison/delta>.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "delta" { };
|
||||
|
||||
options = mkOption {
|
||||
type =
|
||||
with types;
|
||||
let
|
||||
primitiveType = either str (either bool int);
|
||||
sectionType = attrsOf primitiveType;
|
||||
in
|
||||
attrsOf (either primitiveType sectionType);
|
||||
default = { };
|
||||
example = {
|
||||
features = "decorations";
|
||||
whitespace-error-style = "22 reverse";
|
||||
decorations = {
|
||||
commit-decoration-style = "bold yellow box ul";
|
||||
file-style = "bold yellow ul";
|
||||
file-decoration-style = "none";
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Options to configure delta.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
diff-so-fancy = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Enable the {command}`diff-so-fancy` diff colorizer.
|
||||
See <https://github.com/so-fancy/diff-so-fancy>.
|
||||
'';
|
||||
};
|
||||
|
||||
pagerOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"--tabs=4"
|
||||
"-RFX"
|
||||
];
|
||||
description = ''
|
||||
Arguments to be passed to {command}`less`.
|
||||
'';
|
||||
};
|
||||
|
||||
markEmptyLines = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether the first block of an empty line should be colored.
|
||||
'';
|
||||
};
|
||||
|
||||
changeHunkIndicators = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Simplify git header chunks to a more human readable format.
|
||||
'';
|
||||
};
|
||||
|
||||
stripLeadingSymbols = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether the `+` or `-` at
|
||||
line-start should be removed.
|
||||
'';
|
||||
};
|
||||
|
||||
useUnicodeRuler = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
By default, the separator for the file header uses Unicode
|
||||
line-drawing characters. If this is causing output errors on
|
||||
your terminal, set this to false to use ASCII characters instead.
|
||||
'';
|
||||
};
|
||||
|
||||
rulerWidth = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
example = false;
|
||||
description = ''
|
||||
By default, the separator for the file header spans the full
|
||||
width of the terminal. Use this setting to set the width of
|
||||
the file header manually.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
riff = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Enable the <command>riff</command> diff highlighter.
|
||||
See <link xlink:href="https://github.com/walles/riff" />.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "riffdiff" { };
|
||||
|
||||
commandLineOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = literalExpression ''[ "--no-adds-only-special" ]'';
|
||||
apply = lib.concatStringsSep " ";
|
||||
description = ''
|
||||
Command line arguments to include in the <command>RIFF</command> environment variable.
|
||||
|
||||
Run <command>riff --help</command> for a full list of options
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
patdiff = {
|
||||
enable = mkEnableOption "" // {
|
||||
description = ''
|
||||
Whether to enable the {command}`patdiff` differ.
|
||||
See <https://opensource.janestreet.com/patdiff/>
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "patdiff" { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "programs" "git" "signing" "gpgPath" ]
|
||||
[
|
||||
"programs"
|
||||
"git"
|
||||
"signing"
|
||||
"signer"
|
||||
]
|
||||
)
|
||||
];
|
||||
|
||||
config = mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
home.packages = [ cfg.package ];
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion =
|
||||
let
|
||||
enabled = [
|
||||
cfg.delta.enable
|
||||
cfg.diff-so-fancy.enable
|
||||
cfg.difftastic.enable
|
||||
cfg.diff-highlight.enable
|
||||
cfg.riff.enable
|
||||
cfg.patdiff.enable
|
||||
];
|
||||
in
|
||||
lib.count lib.id enabled <= 1;
|
||||
message = "Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' or 'programs.git.diff-highlight' or 'programs.git.patdiff' can be set to true at the same time.";
|
||||
}
|
||||
];
|
||||
|
||||
programs.git.iniContent.user = {
|
||||
name = mkIf (cfg.userName != null) cfg.userName;
|
||||
email = mkIf (cfg.userEmail != null) cfg.userEmail;
|
||||
};
|
||||
|
||||
xdg.configFile = {
|
||||
"git/config".text = lib.generators.toGitINI cfg.iniContent;
|
||||
|
||||
"git/ignore" = mkIf (cfg.ignores != [ ]) {
|
||||
text = concatStringsSep "\n" cfg.ignores + "\n";
|
||||
};
|
||||
|
||||
"git/attributes" = mkIf (cfg.attributes != [ ]) {
|
||||
text = concatStringsSep "\n" cfg.attributes + "\n";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
programs.git.iniContent =
|
||||
let
|
||||
hasSmtp = name: account: account.smtp != null;
|
||||
|
||||
genIdentity =
|
||||
name: account:
|
||||
let
|
||||
inherit (account)
|
||||
address
|
||||
realName
|
||||
smtp
|
||||
userName
|
||||
;
|
||||
in
|
||||
lib.nameValuePair "sendemail.${name}" (
|
||||
if account.msmtp.enable then
|
||||
{
|
||||
sendmailCmd = "${pkgs.msmtp}/bin/msmtp";
|
||||
envelopeSender = "auto";
|
||||
from = "${realName} <${address}>";
|
||||
}
|
||||
else
|
||||
{
|
||||
smtpEncryption =
|
||||
if smtp.tls.enable then
|
||||
(if smtp.tls.useStartTls || lib.versionOlder config.home.stateVersion "20.09" then "tls" else "ssl")
|
||||
else
|
||||
"";
|
||||
smtpSslCertPath = mkIf smtp.tls.enable (toString smtp.tls.certificatesFile);
|
||||
smtpServer = smtp.host;
|
||||
smtpUser = userName;
|
||||
from = "${realName} <${address}>";
|
||||
}
|
||||
// lib.optionalAttrs (smtp.port != null) {
|
||||
smtpServerPort = smtp.port;
|
||||
}
|
||||
);
|
||||
in
|
||||
lib.mapAttrs' genIdentity (lib.filterAttrs hasSmtp config.accounts.email.accounts);
|
||||
}
|
||||
|
||||
(mkIf (cfg.signing != { }) {
|
||||
programs.git = {
|
||||
signing = {
|
||||
format =
|
||||
if (lib.versionOlder config.home.stateVersion "25.05") then
|
||||
(mkOptionDefault "openpgp")
|
||||
else
|
||||
(mkOptionDefault null);
|
||||
signer =
|
||||
let
|
||||
defaultSigners = {
|
||||
openpgp = lib.getExe config.programs.gpg.package;
|
||||
ssh = lib.getExe' pkgs.openssh "ssh-keygen";
|
||||
x509 = lib.getExe' config.programs.gpg.package "gpgsm";
|
||||
};
|
||||
in
|
||||
mkIf (cfg.signing.format != null) (mkOptionDefault defaultSigners.${cfg.signing.format});
|
||||
};
|
||||
|
||||
iniContent = lib.mkMerge [
|
||||
(mkIf (cfg.signing.key != null) {
|
||||
user.signingKey = mkDefault cfg.signing.key;
|
||||
})
|
||||
(mkIf (cfg.signing.signByDefault != null) {
|
||||
commit.gpgSign = mkDefault cfg.signing.signByDefault;
|
||||
tag.gpgSign = mkDefault cfg.signing.signByDefault;
|
||||
})
|
||||
(mkIf (cfg.signing.format != null) {
|
||||
gpg = {
|
||||
format = mkDefault cfg.signing.format;
|
||||
${cfg.signing.format}.program = mkDefault cfg.signing.signer;
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf (cfg.hooks != { }) {
|
||||
programs.git.iniContent = {
|
||||
core.hooksPath =
|
||||
let
|
||||
entries = lib.mapAttrsToList (name: path: { inherit name path; }) cfg.hooks;
|
||||
in
|
||||
toString (pkgs.linkFarm "git-hooks" entries);
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf (cfg.aliases != { }) { programs.git.iniContent.alias = cfg.aliases; })
|
||||
|
||||
(mkIf (lib.isAttrs cfg.extraConfig) {
|
||||
programs.git.iniContent = cfg.extraConfig;
|
||||
})
|
||||
|
||||
(mkIf (lib.isString cfg.extraConfig) {
|
||||
warnings = [
|
||||
''
|
||||
Using programs.git.extraConfig as a string option is
|
||||
deprecated and will be removed in the future. Please
|
||||
change to using it as an attribute set instead.
|
||||
''
|
||||
];
|
||||
|
||||
xdg.configFile."git/config".text = cfg.extraConfig;
|
||||
})
|
||||
|
||||
(mkIf (cfg.includes != [ ]) {
|
||||
xdg.configFile."git/config".text =
|
||||
let
|
||||
include =
|
||||
i:
|
||||
with i;
|
||||
if condition != null then
|
||||
{
|
||||
includeIf.${condition}.path = "${path}";
|
||||
}
|
||||
else
|
||||
{
|
||||
include.path = "${path}";
|
||||
};
|
||||
in
|
||||
lib.mkAfter (concatStringsSep "\n" (map lib.generators.toGitINI (map include cfg.includes)));
|
||||
})
|
||||
|
||||
(mkIf cfg.lfs.enable {
|
||||
home.packages = [ pkgs.git-lfs ];
|
||||
|
||||
programs.git.iniContent.filter.lfs =
|
||||
let
|
||||
skipArg = lib.optional cfg.lfs.skipSmudge "--skip";
|
||||
in
|
||||
{
|
||||
clean = "git-lfs clean -- %f";
|
||||
process = concatStringsSep " " (
|
||||
[
|
||||
"git-lfs"
|
||||
"filter-process"
|
||||
]
|
||||
++ skipArg
|
||||
);
|
||||
required = true;
|
||||
smudge = concatStringsSep " " (
|
||||
[
|
||||
"git-lfs"
|
||||
"smudge"
|
||||
]
|
||||
++ skipArg
|
||||
++ [
|
||||
"--"
|
||||
"%f"
|
||||
]
|
||||
);
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.maintenance.enable {
|
||||
programs.git.iniContent.maintenance.repo = cfg.maintenance.repositories;
|
||||
|
||||
systemd.user.services."git-maintenance@" = {
|
||||
Unit = {
|
||||
Description = "Optimize Git repositories data";
|
||||
Documentation = [ "man:git-maintenance(1)" ];
|
||||
};
|
||||
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
ExecStart =
|
||||
let
|
||||
exe = lib.getExe cfg.package;
|
||||
in
|
||||
''
|
||||
"${exe}" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%i
|
||||
'';
|
||||
LockPersonality = "yes";
|
||||
MemoryDenyWriteExecute = "yes";
|
||||
NoNewPrivileges = "yes";
|
||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_VSOCK";
|
||||
RestrictNamespaces = "yes";
|
||||
RestrictRealtime = "yes";
|
||||
RestrictSUIDSGID = "yes";
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.user.timers =
|
||||
let
|
||||
toSystemdTimer =
|
||||
name: time:
|
||||
lib.attrsets.nameValuePair "git-maintenance@${name}" {
|
||||
Unit.Description = "Optimize Git repositories data";
|
||||
|
||||
Timer = {
|
||||
OnCalendar = time;
|
||||
Persistent = true;
|
||||
};
|
||||
|
||||
Install.WantedBy = [ "timers.target" ];
|
||||
};
|
||||
in
|
||||
lib.attrsets.mapAttrs' toSystemdTimer cfg.maintenance.timers;
|
||||
|
||||
launchd.agents =
|
||||
let
|
||||
baseArguments = [
|
||||
"${lib.getExe cfg.package}"
|
||||
"for-each-repo"
|
||||
"--keep-going"
|
||||
"--config=maintenance.repo"
|
||||
"maintenance"
|
||||
"run"
|
||||
];
|
||||
in
|
||||
{
|
||||
"git-maintenance-hourly" = {
|
||||
enable = true;
|
||||
config = {
|
||||
ProgramArguments = baseArguments ++ [ "--schedule=hourly" ];
|
||||
StartCalendarInterval = map (hour: {
|
||||
Hour = hour;
|
||||
Minute = 53;
|
||||
}) (lib.range 1 23);
|
||||
};
|
||||
};
|
||||
"git-maintenance-daily" = {
|
||||
enable = true;
|
||||
config = {
|
||||
ProgramArguments = baseArguments ++ [ "--schedule=daily" ];
|
||||
StartCalendarInterval = map (weekday: {
|
||||
Weekday = weekday;
|
||||
Hour = 0;
|
||||
Minute = 53;
|
||||
}) (lib.range 1 6);
|
||||
};
|
||||
};
|
||||
"git-maintenance-weekly" = {
|
||||
enable = true;
|
||||
config = {
|
||||
ProgramArguments = baseArguments ++ [ "--schedule=weekly" ];
|
||||
StartCalendarInterval = [
|
||||
{
|
||||
Weekday = 0;
|
||||
Hour = 0;
|
||||
Minute = 53;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.diff-highlight.enable {
|
||||
programs.git.iniContent =
|
||||
let
|
||||
dhCommand = "${cfg.package}/share/git/contrib/diff-highlight/diff-highlight";
|
||||
in
|
||||
{
|
||||
core.pager = "${dhCommand} | ${lib.getExe pkgs.less} ${lib.escapeShellArgs cfg.diff-highlight.pagerOpts}";
|
||||
interactive.diffFilter = dhCommand;
|
||||
};
|
||||
})
|
||||
|
||||
(
|
||||
let
|
||||
difftCommand = concatStringsSep " " [
|
||||
"${lib.getExe cfg.difftastic.package}"
|
||||
"--color ${cfg.difftastic.color}"
|
||||
"--background ${cfg.difftastic.background}"
|
||||
"--display ${cfg.difftastic.display}"
|
||||
];
|
||||
in
|
||||
(lib.mkMerge [
|
||||
(mkIf cfg.difftastic.enable {
|
||||
home.packages = [ cfg.difftastic.package ];
|
||||
programs.git.iniContent = {
|
||||
diff.external = difftCommand;
|
||||
};
|
||||
})
|
||||
(mkIf cfg.difftastic.enableAsDifftool {
|
||||
home.packages = [ cfg.difftastic.package ];
|
||||
programs.git.iniContent = {
|
||||
diff = {
|
||||
tool = lib.mkDefault "difftastic";
|
||||
};
|
||||
difftool = {
|
||||
difftastic = {
|
||||
cmd = "${difftCommand} $LOCAL $REMOTE";
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
])
|
||||
)
|
||||
|
||||
(
|
||||
let
|
||||
deltaPackage = cfg.delta.package;
|
||||
deltaCommand = "${deltaPackage}/bin/delta";
|
||||
in
|
||||
mkIf cfg.delta.enable {
|
||||
home.packages = [ deltaPackage ];
|
||||
|
||||
programs.git.iniContent = {
|
||||
core.pager = deltaCommand;
|
||||
interactive.diffFilter = "${deltaCommand} --color-only";
|
||||
delta = cfg.delta.options;
|
||||
};
|
||||
}
|
||||
)
|
||||
|
||||
(mkIf cfg.diff-so-fancy.enable {
|
||||
home.packages = [ pkgs.diff-so-fancy ];
|
||||
|
||||
programs.git.iniContent =
|
||||
let
|
||||
dsfCommand = "${pkgs.diff-so-fancy}/bin/diff-so-fancy";
|
||||
in
|
||||
{
|
||||
core.pager = "${dsfCommand} | ${pkgs.less}/bin/less ${lib.escapeShellArgs cfg.diff-so-fancy.pagerOpts}";
|
||||
interactive.diffFilter = "${dsfCommand} --patch";
|
||||
diff-so-fancy = {
|
||||
markEmptyLines = cfg.diff-so-fancy.markEmptyLines;
|
||||
changeHunkIndicators = cfg.diff-so-fancy.changeHunkIndicators;
|
||||
stripLeadingSymbols = cfg.diff-so-fancy.stripLeadingSymbols;
|
||||
useUnicodeRuler = cfg.diff-so-fancy.useUnicodeRuler;
|
||||
rulerWidth = mkIf (cfg.diff-so-fancy.rulerWidth != null) (cfg.diff-so-fancy.rulerWidth);
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(
|
||||
let
|
||||
riffExe = baseNameOf (lib.getExe cfg.riff.package);
|
||||
in
|
||||
mkIf cfg.riff.enable {
|
||||
home.packages = [ cfg.riff.package ];
|
||||
|
||||
# https://github.com/walles/riff/blob/b17e6f17ce807c8652bc59cd46758661d23ce358/README.md#usage
|
||||
programs.git.iniContent = {
|
||||
pager = {
|
||||
diff = riffExe;
|
||||
log = riffExe;
|
||||
show = riffExe;
|
||||
};
|
||||
|
||||
interactive.diffFilter = "${riffExe} --color=on";
|
||||
};
|
||||
}
|
||||
)
|
||||
|
||||
(
|
||||
let
|
||||
patdiffPackage = cfg.patdiff.package;
|
||||
patdiffCommand = "${lib.getExe' patdiffPackage "patdiff-git-wrapper"}";
|
||||
in
|
||||
mkIf cfg.patdiff.enable {
|
||||
home.packages = [ patdiffPackage ];
|
||||
|
||||
programs.git.iniContent = {
|
||||
diff.external = patdiffCommand;
|
||||
};
|
||||
}
|
||||
)
|
||||
|
||||
(mkIf (cfg.riff.enable && cfg.riff.commandLineOptions != "") {
|
||||
home.sessionVariables.RIFF = cfg.riff.commandLineOptions;
|
||||
})
|
||||
]
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue