221 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			221 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ config, lib, pkgs, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
  cfg = config.services.gitolite;
 | 
						|
  # Use writeTextDir to not leak Nix store hash into file name
 | 
						|
  pubkeyFile = (pkgs.writeTextDir "gitolite-admin.pub" cfg.adminPubkey) + "/gitolite-admin.pub";
 | 
						|
  hooks = lib.concatMapStrings (hook: "${hook} ") cfg.commonHooks;
 | 
						|
in
 | 
						|
{
 | 
						|
  options = {
 | 
						|
    services.gitolite = {
 | 
						|
      enable = mkOption {
 | 
						|
        type = types.bool;
 | 
						|
        default = false;
 | 
						|
        description = ''
 | 
						|
          Enable gitolite management under the
 | 
						|
          <literal>gitolite</literal> user. After
 | 
						|
          switching to a configuration with Gitolite enabled, you can
 | 
						|
          then run <literal>git clone
 | 
						|
          gitolite@host:gitolite-admin.git</literal> to manage it further.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      dataDir = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        default = "/var/lib/gitolite";
 | 
						|
        description = ''
 | 
						|
          Gitolite home directory (used to store all the repositories).
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      adminPubkey = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        description = ''
 | 
						|
          Initial administrative public key for Gitolite. This should
 | 
						|
          be an SSH Public Key. Note that this key will only be used
 | 
						|
          once, upon the first initialization of the Gitolite user.
 | 
						|
          The key string cannot have any line breaks in it.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      enableGitAnnex = mkOption {
 | 
						|
        type = types.bool;
 | 
						|
        default = false;
 | 
						|
        description = ''
 | 
						|
          Enable git-annex support. Uses the <literal>extraGitoliteRc</literal> option
 | 
						|
          to apply the necessary configuration.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      commonHooks = mkOption {
 | 
						|
        type = types.listOf types.path;
 | 
						|
        default = [];
 | 
						|
        description = ''
 | 
						|
          A list of custom git hooks that get copied to <literal>~/.gitolite/hooks/common</literal>.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      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 <literal>~/.gitolite.rc</literal>.
 | 
						|
 | 
						|
          This should be Perl code that modifies the <literal>%RC</literal>
 | 
						|
          configuration variable. The default <literal>~/.gitolite.rc</literal>
 | 
						|
          content is generated by invoking <literal>gitolite print-default-rc</literal>,
 | 
						|
          and extra configuration from this option is appended to it. The result
 | 
						|
          is placed to Nix store, and the <literal>~/.gitolite.rc</literal> file
 | 
						|
          becomes a symlink to it.
 | 
						|
 | 
						|
          If you already have a customized (or otherwise changed)
 | 
						|
          <literal>~/.gitolite.rc</literal> 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
 | 
						|
          <literal>~/.gitolite.rc</literal>, convert them to appropriate Perl
 | 
						|
          statements, add them to this option, and remove the file.
 | 
						|
 | 
						|
          See also the <literal>enableGitAnnex</literal> option.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      user = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        default = "gitolite";
 | 
						|
        description = ''
 | 
						|
          Gitolite user account. This is the username of the gitolite endpoint.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      group = mkOption {
 | 
						|
        type = types.str;
 | 
						|
        default = "gitolite";
 | 
						|
        description = ''
 | 
						|
          Primary group of the Gitolite user account.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  config = mkIf cfg.enable (
 | 
						|
  let
 | 
						|
    manageGitoliteRc = cfg.extraGitoliteRc != "";
 | 
						|
    rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } 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 <<END >>"$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 {
 | 
						|
    services.gitolite.extraGitoliteRc = optionalString cfg.enableGitAnnex ''
 | 
						|
      # Enable git-annex support:
 | 
						|
      push( @{$RC{ENABLE}}, 'git-annex-shell ua');
 | 
						|
    '';
 | 
						|
 | 
						|
    users.users.${cfg.user} = {
 | 
						|
      description     = "Gitolite user";
 | 
						|
      home            = cfg.dataDir;
 | 
						|
      createHome      = true;
 | 
						|
      uid             = config.ids.uids.gitolite;
 | 
						|
      group           = cfg.group;
 | 
						|
      useDefaultShell = true;
 | 
						|
    };
 | 
						|
    users.groups."${cfg.group}".gid = config.ids.gids.gitolite;
 | 
						|
 | 
						|
    systemd.services."gitolite-init" = {
 | 
						|
      description = "Gitolite initialization";
 | 
						|
      wantedBy    = [ "multi-user.target" ];
 | 
						|
      unitConfig.RequiresMountsFor = cfg.dataDir;
 | 
						|
 | 
						|
      serviceConfig.User = "${cfg.user}";
 | 
						|
      serviceConfig.Type = "oneshot";
 | 
						|
      serviceConfig.RemainAfterExit = true;
 | 
						|
 | 
						|
      path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
 | 
						|
      script =
 | 
						|
      let
 | 
						|
        rcSetupScriptIfCustomFile =
 | 
						|
          if manageGitoliteRc then ''
 | 
						|
            cat <<END
 | 
						|
            <3>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 -f ${hooks} .gitolite/hooks/common/
 | 
						|
            chmod +x .gitolite/hooks/common/*
 | 
						|
          fi
 | 
						|
          gitolite setup # Upgrade if needed
 | 
						|
        '';
 | 
						|
    };
 | 
						|
 | 
						|
    environment.systemPackages = [ pkgs.gitolite pkgs.git ]
 | 
						|
        ++ optional cfg.enableGitAnnex pkgs.gitAndTools.git-annex;
 | 
						|
  });
 | 
						|
}
 |