From dcdf12fd0bcbbc657aaae3962475747d9f3228bd Mon Sep 17 00:00:00 2001 From: tv Date: Sun, 14 Jun 2015 23:55:41 +0200 Subject: modules/tv/git: enable repo-specific hooks --- modules/cd/default.nix | 13 ++++++- modules/tv/git.nix | 94 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/modules/cd/default.nix b/modules/cd/default.nix index 9bb4d0f2..1d621e03 100644 --- a/modules/cd/default.nix +++ b/modules/cd/default.nix @@ -62,7 +62,18 @@ # TODO warn about stale repodirs repos = addNames { testing = { - # TODO hooks = { post-receive = ... + hooks = { + update = '' + #! /bin/sh + set -euf + echo update hook: $* >&2 + ''; + post-update = '' + #! /bin/sh + set -euf + echo post-update hook: $* >&2 + ''; + }; }; }; diff --git a/modules/tv/git.nix b/modules/tv/git.nix index 4d9e200a..052c0499 100644 --- a/modules/tv/git.nix +++ b/modules/tv/git.nix @@ -2,12 +2,12 @@ let inherit (builtins) - attrNames concatLists filter hasAttr head lessThan removeAttrs tail toJSON - typeOf; + attrNames attrValues concatLists filter hasAttr head lessThan removeAttrs + tail toJSON typeOf; inherit (lib) - concatStrings concatStringsSep escapeShellArg hasPrefix listToAttrs - makeSearchPath mapAttrsToList mkIf mkOption removePrefix singleton - sort types unique; + concatMapStringsSep concatStringsSep escapeShellArg hasPrefix + literalExample makeSearchPath mapAttrsToList mkIf mkOption optionalString + removePrefix singleton sort types unique; inherit (pkgs) linkFarm writeScript writeText; @@ -54,8 +54,6 @@ let reponames = rules: sort lessThan (unique (map (x: x.repo.name) rules)); - toShellArgs = xs: toString (map escapeShellArg xs); - # TODO makeGitHooks that uses runCommand instead of scriptFarm? scriptFarm = farm-name: scripts: @@ -99,7 +97,42 @@ in type = types.unspecified; }; repos = mkOption { - type = types.unspecified; + type = types.attrsOf (types.submodule ({ + options = { + name = mkOption { + type = types.str; + description = '' + Repository name. + ''; + }; + hooks = mkOption { + type = types.attrsOf types.str; + description = '' + Repository-specific hooks. + ''; + }; + }; + })); + + default = {}; + + example = literalExample '' + { + testing = { + name = "testing"; + hooks.post-update = ''' + #! /bin/sh + set -euf + echo post-update hook: $* >&2 + '''; + }; + testing2 = { name = "testing2"; }; + } + ''; + + description = '' + Repositories. + ''; }; users = mkOption { type = types.unspecified; @@ -173,23 +206,24 @@ in dataDir=${escapeShellArg cfg.dataDir} mkdir -p "$dataDir" - for reponame in ${toShellArgs (reponames cfg.rules)}; do - repodir=$dataDir/$reponame - if ! test -d "$repodir"; then - mkdir -m 0700 "$repodir" - git init --bare --template=/var/empty "$repodir" - chown -R git: "$repodir" - # branches/ - # description - # hooks/ - # info/ - fi - ln -snf ${hooks} "$repodir/hooks" - done + ${concatMapStringsSep "\n" (repo: + let + hooks = scriptFarm "git-ssh-hooks" (makeHooks repo); + in + '' + reponame=${escapeShellArg repo.name} + repodir=$dataDir/$reponame + if ! test -d "$repodir"; then + mkdir -m 0700 "$repodir" + git init --bare --template=/var/empty "$repodir" + chown -R git: "$repodir" + fi + ln -snf ${hooks} "$repodir/hooks" + '' + ) (attrValues cfg.repos)} ''; - # TODO repo-specific hooks - hooks = scriptFarm "git-ssh-hooks" { + makeHooks = repo: removeAttrs repo.hooks [ "pre-receive" ] // { pre-receive = '' #! /bin/sh set -euf @@ -243,16 +277,10 @@ in fi systemd-cat -p info -t git-ssh echo "$accept_string" - ''; - update = '' - #! /bin/sh - set -euf - echo update hook: $* >&2 - ''; - post-update = '' - #! /bin/sh - set -euf - echo post-update hook: $* >&2 + + ${optionalString (hasAttr "post-receive" repo.hooks) '' + # custom post-receive hook + ${repo.hooks.post-receive}''} ''; }; -- cgit v1.2.3 From 61f60acc3321cf568002914fbdb8da549f6dc2e0 Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 15 Jun 2015 00:34:42 +0200 Subject: modules/tv/git: sanity-check repos on activation --- modules/tv/git.nix | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/modules/tv/git.nix b/modules/tv/git.nix index 052c0499..b7c8b56a 100644 --- a/modules/tv/git.nix +++ b/modules/tv/git.nix @@ -201,11 +201,28 @@ in findutils gawk git + gnugrep + gnused ])} dataDir=${escapeShellArg cfg.dataDir} mkdir -p "$dataDir" + # Notice how the presence of hooks symlinks determine whether + # we manage a repositry or not. + + # Make sure that no existing repository has hooks. We can delete + # symlinks because we assume we created them. + find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks -type l -delete + bad_hooks=$(find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks) + if echo "$bad_hooks" | grep -q .; then + printf "$(printf 'error: unknown hooks:\n%s' \ + "$(echo "$bad_hooks" | sed 's/^/ /')")" \ + >&2 + exit -1 + fi + + # Initialize repositories. ${concatMapStringsSep "\n" (repo: let hooks = scriptFarm "git-ssh-hooks" (makeHooks repo); @@ -218,9 +235,19 @@ in git init --bare --template=/var/empty "$repodir" chown -R git: "$repodir" fi - ln -snf ${hooks} "$repodir/hooks" + ln -s ${hooks} "$repodir/hooks" '' ) (attrValues cfg.repos)} + + # Warn about repositories that exist but aren't mentioned in the + # current configuration (and thus didn't receive a hooks symlink). + unknown_repos=$(find "$dataDir" -mindepth 1 -maxdepth 1 \ + -type d \! -exec test -e '{}/hooks' \; -print) + if echo "$unknown_repos" | grep -q .; then + printf 'warning: stale repositories:\n%s\n' \ + "$(echo "$unknown_repos" | sed 's/^/ /')" \ + >&2 + fi ''; makeHooks = repo: removeAttrs repo.hooks [ "pre-receive" ] // { -- cgit v1.2.3 From 9abc41056323fc0af22dd1cfaf8083f34a633472 Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 15 Jun 2015 00:40:28 +0200 Subject: modules/tv/git: simplify sanity-check printf --- modules/tv/git.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tv/git.nix b/modules/tv/git.nix index b7c8b56a..d264125d 100644 --- a/modules/tv/git.nix +++ b/modules/tv/git.nix @@ -216,8 +216,8 @@ in find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks -type l -delete bad_hooks=$(find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks) if echo "$bad_hooks" | grep -q .; then - printf "$(printf 'error: unknown hooks:\n%s' \ - "$(echo "$bad_hooks" | sed 's/^/ /')")" \ + printf 'error: unknown hooks:\n%s\n' \ + "$(echo "$bad_hooks" | sed 's/^/ /')" \ >&2 exit -1 fi -- cgit v1.2.3