diff options
Diffstat (limited to '')
-rw-r--r-- | modules/git/default.nix | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/modules/git/default.nix b/modules/git/default.nix new file mode 100644 index 0000000..a65c31e --- /dev/null +++ b/modules/git/default.nix @@ -0,0 +1,300 @@ +{ + config, + inputs, + lib, + libNginx, + libPlausible, + pkgs, + ... +}: +with lib; +let + cfg = config.nixfiles.modules.git; +in +{ + options.nixfiles.modules.git = { + client.enable = mkEnableOption "Git client"; + + server = { + enable = mkEnableOption "Git server"; + + domain = mkOption { + description = "Domain name sans protocol scheme."; + type = with types; nullOr str; + default = "git.${config.networking.domain}"; + }; + + package = mkOption { + description = "Package."; + type = types.package; + default = pkgs.cgit; + }; + }; + }; + + config = mkMerge [ + (mkIf cfg.client.enable { + secrets = { + glab-cli-config = { + file = "${inputs.self}/secrets/glab-cli-config"; + path = "${config.dirs.config}/glab-cli/config.yml"; + owner = my.username; + }; + gh-hosts = { + file = "${inputs.self}/secrets/gh-hosts"; + path = "${config.dirs.config}/gh/hosts.yml"; + owner = my.username; + }; + hut = { + file = "${inputs.self}/secrets/hut"; + path = "${config.dirs.config}/hut/config"; + owner = my.username; + }; + }; + + nixfiles.modules.common.shell.aliases = { + gl = "glab"; + ht = "hut"; + }; + + hm = { + home.packages = with pkgs; [ + git-extras + glab + hut + ]; + + programs = { + git = { + enable = true; + + package = pkgs.git.override { + doInstallCheck = false; + pythonSupport = false; + sendEmailSupport = true; + withLibsecret = false; + withSsh = true; + }; + + userName = my.fullname; + userEmail = my.email; + signing = { + inherit (my.pgp) key; + signByDefault = true; + }; + + extraConfig = + { + color.ui = true; + core.whitespace = "trailing-space"; + init.defaultBranch = "master"; + status.submoduleSummary = true; + commit.verbose = true; + push.autoSetupRemote = true; + pull.rebase = true; + rebase = { + autoStash = true; + autoSquash = true; + }; + rerere.enabled = true; + branch.sort = "-committerdate"; + diff = { + mnemonicPrefix = true; + renames = "copies"; + submodule = "log"; + }; + submodule.recurse = true; + sendemail = rec { + smtpServer = my.domain.shire; + smtpUser = "${my.username}@${smtpServer}"; + smtpEncryption = "ssl"; + smtpServerPort = 465; + annotate = true; + confirm = "always"; + }; + column.ui = "auto"; + github.user = my.username; + gitlab.user = my.username; + } + // mapAttrs' (name: value: nameValuePair ''url "git@${value}:"'' { insteadOf = "${name}:"; }) { + "bitbucket" = "bitbucket.com"; + "codeberg" = "codeberg.org"; + "github" = "github.com"; + "gitlab" = "gitlab.com"; + "sourcehut" = "git.sr.ht"; + } + // + mapAttrs' (name: values: nameValuePair ''url "https://${values}/"'' { insteadOf = "${name}:"; }) + { + "alpine" = "gitlab.alpinelinux.org"; + "debian" = "salsa.debian.org"; + "freedesktop" = "gitlab.freedesktop.org"; + "gnome" = "gitlab.gnome.org"; + "haskell" = "gitlab.haskell.org"; + "homotopic" = "gitlab.homotopic.tech"; + "horizon" = "gitlab.horizon-haskell.net"; + "kde" = "invent.kde.org"; + "nixca" = "gitlab.nixca.dev"; + "notabug" = "notabug.org"; + "opencode" = "opencode.net"; + "torproject" = "gitlab.torproject.org"; + "videolan" = "code.videolan.org"; + }; + + aliases = + let + git = getExe config.hm.programs.git.package; + curl = getExe pkgs.curl; + in + { + amend = "commit --amend"; + cat = "cat-file -p"; + fast = "clone --depth=1"; + fixup = "commit --fixup"; + fuck = "!${git} reset --hard && ${git} clean --force -dx"; + get = "pull --all --recurse-submodules --autostash"; + gud = ''commit -m "git gud"''; + refresh = "clean --force -dx"; + tree = "log --graph --date=relative --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ad)%Creset'"; + uncommit = "reset --soft HEAD~1"; + untrack = "rm --cache --"; + wtc = "!${curl} -sq whatthecommit.com/index.txt | ${git} commit -F -"; + }; + + # All helper tools/editor generated files should go here. This must be + # kept void of any project-specific or residual files. + ignores = [ + "*~" + ".DS_Store" + ".cache/clangd/" + ".ccls-cache/" + ".gdb_history" + ".netrwhist" + ".projectile" + "[._]*.s[a-v][a-z]" + "[._]*.sw[a-p]" + "[._]s[a-rt-v][a-z]" + "[._]ss[a-gi-z]" + "[._]sw[a-p]" + "\#*\#" + "compile_commands*.json" + "cscope.*" + "vgcore.*" + ]; + }; + + gh = { + enable = true; + settings.git_protocol = "ssh"; + }; + }; + }; + }) + (mkIf cfg.server.enable { + ark.directories = [ config.services.gitolite.dataDir ]; + + nixfiles.modules.nginx = { + enable = true; + virtualHosts.${cfg.server.domain} = { + locations = { + "/".extraConfig = + let + cgitrc = pkgs.writeText "cgitrc" '' + root-title=github sux (⩺_⩹) + root-desc=https://github.com/azahi + + clone-url=https://${cfg.server.domain}/$CGIT_REPO_URL + + logo=/cgit-custom-logo.gif + favicon=/cgit-custom-favicon.gif + css=/cgit-custom-style.css + + about-filter=${cfg.server.package}/lib/cgit/filters/about-formatting.sh + source-filter=${cfg.server.package}/lib/cgit/filters/syntax-highlighting.py + commit-filter=${cfg.server.package}/lib/cgit/filters/commit-links.sh + + enable-git-config=1 + enable-gitweb-owner=1 + remove-suffix=1 + + readme=:README + readme=:README.md + readme=:README.org + readme=:README.txt + readme=:readme + readme=:readme.md + readme=:readme.org + readme=:readme.txt + + scan-path=${config.services.gitolite.dataDir}/repositories + ''; + in + '' + include ${config.services.nginx.package}/conf/fastcgi_params; + fastcgi_split_path_info ^(/?)(.+)$; + fastcgi_pass unix:${config.services.fcgiwrap.socketAddress}; + fastcgi_param SCRIPT_FILENAME ${cfg.server.package}/cgit/cgit.cgi; + fastcgi_param CGIT_CONFIG ${cgitrc}; + fastcgi_param PATH_INFO $uri; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + + ${libNginx.config.appendHead [ + ''<meta name="go-import" content="$host$uri git https://$host$uri">'' + (libPlausible.htmlPlausibleScript { inherit (cfg.server) domain; }) + ]} + ''; + "~* ^.+(cgit.css|robots.txt)$".extraConfig = '' + root ${cfg.server.package}/cgit; + ''; + "~* ^.+cgit-custom-logo.gif$".extraConfig = '' + alias ${./logo.gif}; + ''; + "~* ^.+cgit-custom-favicon.gif$".extraConfig = '' + alias ${./favicon.ico}; + ''; + "~* ^.+cgit-custom-style.css$".extraConfig = + let + css = pkgs.writeText "custom.css" '' + @import url("cgit.css"); + + div#cgit { + font-family: monospace; + -moz-tab-size: 4; + tab-size: 4; + } + ''; + in + '' + alias ${css}; + ''; + }; + }; + }; + + services = + let + user = "git"; + group = "git"; + in + { + gitolite = { + enable = true; + inherit user group; + adminPubkey = my.ssh.key; + extraGitoliteRc = '' + # This allows hiding repositories via "cgit.ignore"[1]. + # + # [1]: https://www.omarpolo.com/post/cgit-gitolite.html + $RC{GIT_CONFIG_KEYS} = '.*'; + ''; + }; + + fcgiwrap = { + enable = true; + inherit user group; + }; + }; + }) + ]; +} |