From c73a3813fa0fed7620fda45f1414e56e35a3538d Mon Sep 17 00:00:00 2001 From: Pavel Goran Date: Fri, 22 Sep 2017 09:16:36 +0700 Subject: [PATCH] nixos/gitolite: customize .gitolite.rc declaratively Add the `extraGitoliteRc` option to customize the `.gitolite.rc` configuration file declaratively. Resolves #29249. --- nixos/modules/services/misc/gitolite.nix | 126 ++++++++++++++++++++--- 1 file changed, 111 insertions(+), 15 deletions(-) diff --git a/nixos/modules/services/misc/gitolite.nix b/nixos/modules/services/misc/gitolite.nix index 60fc9d58ed07..d803a4e0bf12 100644 --- a/nixos/modules/services/misc/gitolite.nix +++ b/nixos/modules/services/misc/gitolite.nix @@ -49,6 +49,35 @@ in ''; }; + extraGitoliteRc = mkOption { + type = types.lines; + default = ""; + example = literalExample '' + $RC{UMASK} = 0027; + $RC{SITE_INFO} = 'This is our private repository host'; + push( @{$RC{ENABLE}}, 'Kindergarten' ); # enable the command/feature + @{$RC{ENABLE}} = grep { $_ ne 'desc' } @{$RC{ENABLE}}; # disable the command/feature + ''; + description = '' + Extra configuration to append to the default ~/.gitolite.rc. + + This should be Perl code that modifies the %RC + configuration variable. The default ~/.gitolite.rc + content is generated by invoking gitolite print-default-rc, + and extra configuration from this option is appended to it. The result + is placed to Nix store, and the ~/.gitolite.rc file + becomes a symlink to it. + + If you already have a customized (or otherwise changed) + ~/.gitolite.rc file, NixOS will refuse to replace + it with a symlink, and the `gitolite-init` initialization service + will fail. In this situation, in order to use this option, you + will need to take any customizations you may have in + ~/.gitolite.rc, convert them to appropriate Perl + statements, add them to this option, and remove the file. + ''; + }; + user = mkOption { type = types.str; default = "gitolite"; @@ -59,7 +88,34 @@ in }; }; - config = mkIf cfg.enable { + config = mkIf cfg.enable ( + let + manageGitoliteRc = cfg.extraGitoliteRc != ""; + rcDir = pkgs.runCommand "gitolite-rc" { } rcDirScript; + rcDirScript = + '' + mkdir "$out" + export HOME=temp-home + mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it + '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default" + cat <>"$out/gitolite.rc" + # This file is managed by NixOS. + # Use services.gitolite options to control it. + + END + cat "$out/gitolite.rc.default" >>"$out/gitolite.rc" + '' + + optionalString (cfg.extraGitoliteRc != "") '' + echo -n ${escapeShellArg '' + + # Added by NixOS: + ${removeSuffix "\n" cfg.extraGitoliteRc} + + # per perl rules, this should be the last line in such a file: + 1; + ''} >>"$out/gitolite.rc" + ''; + in { users.extraUsers.${cfg.user} = { description = "Gitolite user"; home = cfg.dataDir; @@ -77,21 +133,61 @@ in serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; - path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash config.programs.ssh.package ]; - script = '' - cd ${cfg.dataDir} - mkdir -p .gitolite/logs - if [ ! -d repositories ]; then - gitolite setup -pk ${pubkeyFile} - fi - if [ -n "${hooks}" ]; then - cp ${hooks} .gitolite/hooks/common/ - chmod +x .gitolite/hooks/common/* - fi - gitolite setup # Upgrade if needed - ''; + path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ]; + script = + let + rcSetupScriptIfCustomFile = + if manageGitoliteRc then '' + cat <ERROR: NixOS can't apply declarative configuration + <3>to your .gitolite.rc file, because it seems to be + <3>already customized manually. + <3>See the services.gitolite.extraGitoliteRc option + <3>in "man configuration.nix" for more information. + END + # Not sure if the line below addresses the issue directly or just + # adds a delay, but without it our error message often doesn't + # show up in `systemctl status gitolite-init`. + journalctl --flush + exit 1 + '' else '' + : + ''; + rcSetupScriptIfDefaultFileOrStoreSymlink = + if manageGitoliteRc then '' + ln -sf "${rcDir}/gitolite.rc" "$GITOLITE_RC" + '' else '' + [[ -L "$GITOLITE_RC" ]] && rm -f "$GITOLITE_RC" + ''; + in + '' + cd ${cfg.dataDir} + mkdir -p .gitolite/logs + + GITOLITE_RC=.gitolite.rc + GITOLITE_RC_DEFAULT=${rcDir}/gitolite.rc.default + if ( [[ ! -e "$GITOLITE_RC" ]] && [[ ! -L "$GITOLITE_RC" ]] ) || + ( [[ -f "$GITOLITE_RC" ]] && diff -q "$GITOLITE_RC" "$GITOLITE_RC_DEFAULT" >/dev/null ) || + ( [[ -L "$GITOLITE_RC" ]] && [[ "$(readlink "$GITOLITE_RC")" =~ ^/nix/store/ ]] ) + then + '' + rcSetupScriptIfDefaultFileOrStoreSymlink + + '' + else + '' + rcSetupScriptIfCustomFile + + '' + fi + + if [ ! -d repositories ]; then + gitolite setup -pk ${pubkeyFile} + fi + if [ -n "${hooks}" ]; then + cp ${hooks} .gitolite/hooks/common/ + chmod +x .gitolite/hooks/common/* + fi + gitolite setup # Upgrade if needed + ''; }; environment.systemPackages = [ pkgs.gitolite pkgs.git ]; - }; + }); }