python3Packages.orjson: Disable failing tests on 32 bit
[NixPkgs.git] / nixos / modules / services / misc / gitolite.nix
blob012abda2d76f931a874b519af5728b8cb9ce5a8c
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.gitolite;
7   # Use writeTextDir to not leak Nix store hash into file name
8   pubkeyFile = (pkgs.writeTextDir "gitolite-admin.pub" cfg.adminPubkey) + "/gitolite-admin.pub";
9   hooks = lib.concatMapStrings (hook: "${hook} ") cfg.commonHooks;
12   options = {
13     services.gitolite = {
14       enable = mkOption {
15         type = types.bool;
16         default = false;
17         description = lib.mdDoc ''
18           Enable gitolite management under the
19           `gitolite` user. After
20           switching to a configuration with Gitolite enabled, you can
21           then run `git clone gitolite@host:gitolite-admin.git` to manage it further.
22         '';
23       };
25       dataDir = mkOption {
26         type = types.str;
27         default = "/var/lib/gitolite";
28         description = lib.mdDoc ''
29           The gitolite home directory used to store all repositories. If left as the default value
30           this directory will automatically be created before the gitolite server starts, otherwise
31           the sysadmin is responsible for ensuring the directory exists with appropriate ownership
32           and permissions.
33         '';
34       };
36       adminPubkey = mkOption {
37         type = types.str;
38         description = lib.mdDoc ''
39           Initial administrative public key for Gitolite. This should
40           be an SSH Public Key. Note that this key will only be used
41           once, upon the first initialization of the Gitolite user.
42           The key string cannot have any line breaks in it.
43         '';
44       };
46       enableGitAnnex = mkOption {
47         type = types.bool;
48         default = false;
49         description = lib.mdDoc ''
50           Enable git-annex support. Uses the `extraGitoliteRc` option
51           to apply the necessary configuration.
52         '';
53       };
55       commonHooks = mkOption {
56         type = types.listOf types.path;
57         default = [];
58         description = lib.mdDoc ''
59           A list of custom git hooks that get copied to `~/.gitolite/hooks/common`.
60         '';
61       };
63       extraGitoliteRc = mkOption {
64         type = types.lines;
65         default = "";
66         example = literalExpression ''
67           '''
68             $RC{UMASK} = 0027;
69             $RC{SITE_INFO} = 'This is our private repository host';
70             push( @{$RC{ENABLE}}, 'Kindergarten' ); # enable the command/feature
71             @{$RC{ENABLE}} = grep { $_ ne 'desc' } @{$RC{ENABLE}}; # disable the command/feature
72           '''
73         '';
74         description = lib.mdDoc ''
75           Extra configuration to append to the default `~/.gitolite.rc`.
77           This should be Perl code that modifies the `%RC`
78           configuration variable. The default `~/.gitolite.rc`
79           content is generated by invoking `gitolite print-default-rc`,
80           and extra configuration from this option is appended to it. The result
81           is placed to Nix store, and the `~/.gitolite.rc` file
82           becomes a symlink to it.
84           If you already have a customized (or otherwise changed)
85           `~/.gitolite.rc` file, NixOS will refuse to replace
86           it with a symlink, and the `gitolite-init` initialization service
87           will fail. In this situation, in order to use this option, you
88           will need to take any customizations you may have in
89           `~/.gitolite.rc`, convert them to appropriate Perl
90           statements, add them to this option, and remove the file.
92           See also the `enableGitAnnex` option.
93         '';
94       };
96       user = mkOption {
97         type = types.str;
98         default = "gitolite";
99         description = lib.mdDoc ''
100           Gitolite user account. This is the username of the gitolite endpoint.
101         '';
102       };
104       description = mkOption {
105         type = types.str;
106         default = "Gitolite user";
107         description = lib.mdDoc ''
108           Gitolite user account's description.
109         '';
110       };
112       group = mkOption {
113         type = types.str;
114         default = "gitolite";
115         description = lib.mdDoc ''
116           Primary group of the Gitolite user account.
117         '';
118       };
119     };
120   };
122   config = mkIf cfg.enable (
123   let
124     manageGitoliteRc = cfg.extraGitoliteRc != "";
125     rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } rcDirScript;
126     rcDirScript =
127       ''
128         mkdir "$out"
129         export HOME=temp-home
130         mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it
131         '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default"
132         cat <<END >>"$out/gitolite.rc"
133         # This file is managed by NixOS.
134         # Use services.gitolite options to control it.
136         END
137         cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
138       '' +
139       optionalString (cfg.extraGitoliteRc != "") ''
140         echo -n ${escapeShellArg ''
142           # Added by NixOS:
143           ${removeSuffix "\n" cfg.extraGitoliteRc}
145           # per perl rules, this should be the last line in such a file:
146           1;
147         ''} >>"$out/gitolite.rc"
148       '';
149   in {
150     services.gitolite.extraGitoliteRc = optionalString cfg.enableGitAnnex ''
151       # Enable git-annex support:
152       push( @{$RC{ENABLE}}, 'git-annex-shell ua');
153     '';
155     users.users.${cfg.user} = {
156       description     = cfg.description;
157       home            = cfg.dataDir;
158       uid             = config.ids.uids.gitolite;
159       group           = cfg.group;
160       useDefaultShell = true;
161     };
162     users.groups.${cfg.group}.gid = config.ids.gids.gitolite;
164     systemd.services.gitolite-init = {
165       description = "Gitolite initialization";
166       wantedBy    = [ "multi-user.target" ];
167       unitConfig.RequiresMountsFor = cfg.dataDir;
169       environment = {
170         GITOLITE_RC = ".gitolite.rc";
171         GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
172       };
174       serviceConfig = mkMerge [
175         (mkIf (cfg.dataDir == "/var/lib/gitolite") {
176           StateDirectory = "gitolite gitolite/.gitolite gitolite/.gitolite/logs";
177           StateDirectoryMode = "0750";
178         })
179         {
180           Type = "oneshot";
181           User = cfg.user;
182           Group = cfg.group;
183           WorkingDirectory = "~";
184           RemainAfterExit = true;
185         }
186       ];
188       path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
189       script =
190       let
191         rcSetupScriptIfCustomFile =
192           if manageGitoliteRc then ''
193             cat <<END
194             <3>ERROR: NixOS can't apply declarative configuration
195             <3>to your .gitolite.rc file, because it seems to be
196             <3>already customized manually.
197             <3>See the services.gitolite.extraGitoliteRc option
198             <3>in "man configuration.nix" for more information.
199             END
200             # Not sure if the line below addresses the issue directly or just
201             # adds a delay, but without it our error message often doesn't
202             # show up in `systemctl status gitolite-init`.
203             journalctl --flush
204             exit 1
205           '' else ''
206             :
207           '';
208         rcSetupScriptIfDefaultFileOrStoreSymlink =
209           if manageGitoliteRc then ''
210             ln -sf "${rcDir}/gitolite.rc" "$GITOLITE_RC"
211           '' else ''
212             [[ -L "$GITOLITE_RC" ]] && rm -f "$GITOLITE_RC"
213           '';
214       in
215         ''
216           if ( [[ ! -e "$GITOLITE_RC" ]] && [[ ! -L "$GITOLITE_RC" ]] ) ||
217              ( [[ -f "$GITOLITE_RC" ]] && diff -q "$GITOLITE_RC" "$GITOLITE_RC_DEFAULT" >/dev/null ) ||
218              ( [[ -L "$GITOLITE_RC" ]] && [[ "$(readlink "$GITOLITE_RC")" =~ ^/nix/store/ ]] )
219           then
220         '' + rcSetupScriptIfDefaultFileOrStoreSymlink +
221         ''
222           else
223         '' + rcSetupScriptIfCustomFile +
224         ''
225           fi
227           if [ ! -d repositories ]; then
228             gitolite setup -pk ${pubkeyFile}
229           fi
230           if [ -n "${hooks}" ]; then
231             cp -f ${hooks} .gitolite/hooks/common/
232             chmod +x .gitolite/hooks/common/*
233           fi
234           gitolite setup # Upgrade if needed
235         '';
236     };
238     environment.systemPackages = [ pkgs.gitolite pkgs.git ]
239         ++ optional cfg.enableGitAnnex pkgs.git-annex;
240   });