1
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-06-20 08:29:20 +03:00
nixpkgs/nixos/modules/services/networking/cgit.nix
Silvan Mosberger 4f0dadbf38 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build a08b3a4d19.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:26:33 +01:00

288 lines
8.1 KiB
Nix
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
config,
lib,
pkgs,
...
}:
let
cfgs = config.services.cgit;
settingType =
with lib.types;
oneOf [
bool
int
str
];
repeatedSettingType =
with lib.types;
oneOf [
settingType
(listOf settingType)
];
genAttrs' = names: f: lib.listToAttrs (map f names);
regexEscape =
let
# taken from https://github.com/python/cpython/blob/05cb728d68a278d11466f9a6c8258d914135c96c/Lib/re.py#L251-L266
special = [
"("
")"
"["
"]"
"{"
"}"
"?"
"*"
"+"
"-"
"|"
"^"
"$"
"\\"
"."
"&"
"~"
"#"
" "
"\t"
"\n"
"\r"
" " # \v / 0x0B
" " # \f / 0x0C
];
in
lib.replaceStrings special (map (c: "\\${c}") special);
stripLocation = cfg: lib.removeSuffix "/" cfg.nginx.location;
regexLocation = cfg: regexEscape (stripLocation cfg);
mkFastcgiPass = name: cfg: ''
${
if cfg.nginx.location == "/" then
''
fastcgi_param PATH_INFO $uri;
''
else
''
fastcgi_split_path_info ^(${regexLocation cfg})(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
''
}fastcgi_pass unix:${config.services.fcgiwrap.instances."cgit-${name}".socket.address};
'';
cgitrcLine =
name: value:
"${name}=${
if value == true then
"1"
else if value == false then
"0"
else
toString value
}";
# list value as multiple lines (for "readme" for example)
cgitrcEntry =
name: value: if lib.isList value then map (cgitrcLine name) value else [ (cgitrcLine name value) ];
mkCgitrc =
cfg:
pkgs.writeText "cgitrc" ''
# global settings
${lib.concatStringsSep "\n" (
lib.flatten (
lib.mapAttrsToList cgitrcEntry ({ virtual-root = cfg.nginx.location; } // cfg.settings)
)
)}
${lib.optionalString (cfg.scanPath != null) (cgitrcLine "scan-path" cfg.scanPath)}
# repository settings
${lib.concatStrings (
lib.mapAttrsToList (url: settings: ''
${cgitrcLine "repo.url" url}
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: cgitrcLine "repo.${name}") settings)}
'') cfg.repos
)}
# extra config
${cfg.extraConfig}
'';
fcgiwrapUnitName = name: "fcgiwrap-cgit-${name}";
fcgiwrapRuntimeDir = name: "/run/${fcgiwrapUnitName name}";
gitProjectRoot =
name: cfg: if cfg.scanPath != null then cfg.scanPath else "${fcgiwrapRuntimeDir name}/repos";
in
{
options = {
services.cgit = lib.mkOption {
description = "Configure cgit instances.";
default = { };
type = lib.types.attrsOf (
lib.types.submodule (
{ config, ... }:
{
options = {
enable = lib.mkEnableOption "cgit";
package = lib.mkPackageOption pkgs "cgit" { };
nginx.virtualHost = lib.mkOption {
description = "VirtualHost to serve cgit on, defaults to the attribute name.";
type = lib.types.str;
default = config._module.args.name;
example = "git.example.com";
};
nginx.location = lib.mkOption {
description = "Location to serve cgit under.";
type = lib.types.str;
default = "/";
example = "/git/";
};
repos = lib.mkOption {
description = "cgit repository settings, see cgitrc(5)";
type = with lib.types; attrsOf (attrsOf settingType);
default = { };
example = {
blah = {
path = "/var/lib/git/example";
desc = "An example repository";
};
};
};
scanPath = lib.mkOption {
description = "A path which will be scanned for repositories.";
type = lib.types.nullOr lib.types.path;
default = null;
example = "/var/lib/git";
};
settings = lib.mkOption {
description = "cgit configuration, see cgitrc(5)";
type = lib.types.attrsOf repeatedSettingType;
default = { };
example = lib.literalExpression ''
{
enable-follow-links = true;
source-filter = "''${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py";
}
'';
};
extraConfig = lib.mkOption {
description = "These lines go to the end of cgitrc verbatim.";
type = lib.types.lines;
default = "";
};
user = lib.mkOption {
description = "User to run the cgit service as.";
type = lib.types.str;
default = "cgit";
};
group = lib.mkOption {
description = "Group to run the cgit service as.";
type = lib.types.str;
default = "cgit";
};
};
}
)
);
};
};
config = lib.mkIf (lib.any (cfg: cfg.enable) (lib.attrValues cfgs)) {
assertions = lib.mapAttrsToList (vhost: cfg: {
assertion = !cfg.enable || (cfg.scanPath == null) != (cfg.repos == { });
message = "Exactly one of services.cgit.${vhost}.scanPath or services.cgit.${vhost}.repos must be set.";
}) cfgs;
users = lib.mkMerge (
lib.flip lib.mapAttrsToList cfgs (
_: cfg: {
users.${cfg.user} = {
isSystemUser = true;
inherit (cfg) group;
};
groups.${cfg.group} = { };
}
)
);
services.fcgiwrap.instances = lib.flip lib.mapAttrs' cfgs (
name: cfg:
lib.nameValuePair "cgit-${name}" {
process = { inherit (cfg) user group; };
socket = { inherit (config.services.nginx) user group; };
}
);
systemd.services = lib.flip lib.mapAttrs' cfgs (
name: cfg:
lib.nameValuePair (fcgiwrapUnitName name) (
lib.mkIf (cfg.repos != { }) {
serviceConfig.RuntimeDirectory = fcgiwrapUnitName name;
preStart = ''
GIT_PROJECT_ROOT=${lib.escapeShellArg (gitProjectRoot name cfg)}
mkdir -p "$GIT_PROJECT_ROOT"
cd "$GIT_PROJECT_ROOT"
${lib.concatLines (
lib.flip lib.mapAttrsToList cfg.repos (
name: repo: ''
ln -s ${lib.escapeShellArg repo.path} ${lib.escapeShellArg name}
''
)
)}
'';
}
)
);
services.nginx.enable = true;
services.nginx.virtualHosts = lib.mkMerge (
lib.mapAttrsToList (name: cfg: {
${cfg.nginx.virtualHost} = {
locations =
(genAttrs' [ "cgit.css" "cgit.png" "favicon.ico" "robots.txt" ] (
fileName:
lib.nameValuePair "= ${stripLocation cfg}/${fileName}" {
extraConfig = ''
alias ${cfg.package}/cgit/${fileName};
'';
}
))
// {
"~ ${regexLocation cfg}/.+/(info/refs|git-upload-pack)" = {
fastcgiParams = rec {
SCRIPT_FILENAME = "${pkgs.git}/libexec/git-core/git-http-backend";
GIT_HTTP_EXPORT_ALL = "1";
GIT_PROJECT_ROOT = gitProjectRoot name cfg;
HOME = GIT_PROJECT_ROOT;
};
extraConfig = mkFastcgiPass name cfg;
};
"${stripLocation cfg}/" = {
fastcgiParams = {
SCRIPT_FILENAME = "${cfg.package}/cgit/cgit.cgi";
QUERY_STRING = "$args";
HTTP_HOST = "$server_name";
CGIT_CONFIG = mkCgitrc cfg;
};
extraConfig = mkFastcgiPass name cfg;
};
};
};
}) cfgs
);
};
}