diff options
Diffstat (limited to 'tv/5pkgs')
-rw-r--r-- | tv/5pkgs/default.nix | 1 | ||||
-rw-r--r-- | tv/5pkgs/git-hooks/default.nix | 168 |
2 files changed, 169 insertions, 0 deletions
diff --git a/tv/5pkgs/default.nix b/tv/5pkgs/default.nix index 2108d972c..0f4274025 100644 --- a/tv/5pkgs/default.nix +++ b/tv/5pkgs/default.nix @@ -12,6 +12,7 @@ "%@" ''; ff = pkgs.callPackage ./ff {}; + git-hooks = pkgs.callPackage ./git-hooks {}; viljetic-pages = pkgs.callPackage ./viljetic-pages {}; xmonad-tv = let src = pkgs.writeNixFromCabal "xmonad-tv.nix" ./xmonad-tv; in diff --git a/tv/5pkgs/git-hooks/default.nix b/tv/5pkgs/git-hooks/default.nix new file mode 100644 index 000000000..5697c31be --- /dev/null +++ b/tv/5pkgs/git-hooks/default.nix @@ -0,0 +1,168 @@ +{ lib, pkgs, ... }: + +with lib; + +let + out = { + inherit irc-announce; + }; + + # TODO irc-announce should return a derivation + irc-announce = { nick, channel, server, port ? 6667, verbose ? false }: '' + #! /bin/sh + set -euf + + export PATH=${makeSearchPath "bin" (with pkgs; [ + coreutils + git + gnused + ])} + + green() { printf '\x0303,99%s\x0F' "$1"; } + red() { printf '\x0304,99%s\x0F' "$1"; } + orange() { printf '\x0307,99%s\x0F' "$1"; } + pink() { printf '\x0313,99%s\x0F' "$1"; } + gray() { printf '\x0314,99%s\x0F' "$1"; } + + unset message + add_message() { + message="''${message+$message + }$*" + } + + nick=${escapeShellArg nick} + channel=${escapeShellArg channel} + server=${escapeShellArg server} + port=${toString port} + + host=$nick + cgit_endpoint=http://cgit.$host + + empty=0000000000000000000000000000000000000000 + + while read oldrev newrev ref; do + + if [ $oldrev = $empty ]; then + receive_mode=create + elif [ $newrev = $empty ]; then + receive_mode=delete + elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then + receive_mode=fast-forward + else + receive_mode=non-fast-forward + fi + + h=$(echo $ref | sed 's:^refs/heads/::') + + # empty_tree=$(git hash-object -t tree /dev/null) + empty_tree=4b825dc6 + + id=$(echo $newrev | cut -b-7) + id2=$(echo $oldrev | cut -b-7) + if [ $newrev = $empty ]; then id=$empty_tree; fi + if [ $oldrev = $empty ]; then id2=$empty_tree; fi + + case $receive_mode in + create) + link="$cgit_endpoint/$GIT_SSH_REPO/?h=$h" + ;; + delete) + link="$cgit_endpoint/$GIT_SSH_REPO/ ($h)" + ;; + fast-forward|non-fast-forward) + link="$cgit_endpoint/$GIT_SSH_REPO/diff/?h=$h&id=$id&id2=$id2" + ;; + esac + + #$host $GIT_SSH_REPO $ref $link + add_message $(pink push) $link $(gray "($receive_mode)") + + ${optionalString verbose '' + add_message "$( + git log \ + --format="$(orange %h) %s $(gray '(%ar)')" \ + --reverse \ + $id2..$id + + git diff --stat $id2..$id \ + | sed '$!s/\(+*\)\(-*\)$/'$(green '\1')$(red '\2')'/' + )" + ''} + + done + + if test -n "''${message-}"; then + exec ${irc-announce-script} \ + "$server" \ + "$port" \ + "$nick" \ + "$channel" \ + "$message" + fi + ''; + + irc-announce-script = pkgs.writeScript "irc-announce-script" '' + #! /bin/sh + set -euf + + export PATH=${makeSearchPath "bin" (with pkgs; [ + coreutils + gawk + gnused + netcat + nettools + ])} + + IRC_SERVER=$1 + IRC_PORT=$2 + IRC_NICK=$3$$ + IRC_CHANNEL=$4 + message=$5 + + export IRC_CHANNEL # for privmsg_cat + + # echo2 and cat2 are used output to both, stdout and stderr + # This is used to see what we send to the irc server. (debug output) + echo2() { echo "$*"; echo "$*" >&2; } + cat2() { tee /dev/stderr; } + + # privmsg_cat transforms stdin to a privmsg + privmsg_cat() { awk '{ print "PRIVMSG "ENVIRON["IRC_CHANNEL"]" :"$0 }'; } + + # ircin is used to feed the output of netcat back to the "irc client" + # so we can implement expect-like behavior with sed^_^ + # XXX mkselfdestructingtmpfifo would be nice instead of this cruft + tmpdir="$(mktemp -d irc-announce_XXXXXXXX)" + cd "$tmpdir" + mkfifo ircin + trap " + rm ircin + cd '$OLDPWD' + rmdir '$tmpdir' + trap - EXIT INT QUIT + " EXIT INT QUIT + + { + echo2 "USER $LOGNAME 0 * :$LOGNAME@$(hostname)" + echo2 "NICK $IRC_NICK" + + # wait for MODE message + sed -n '/^:[^ ]* MODE /q' + + echo2 "JOIN $IRC_CHANNEL" + + printf '%s' "$message" \ + | privmsg_cat \ + | cat2 + + echo2 "PART $IRC_CHANNEL" + + # wait for PART confirmation + sed -n '/:'"$IRC_NICK"'![^ ]* PART /q' + + echo2 'QUIT :Gone to have lunch' + } < ircin \ + | nc "$IRC_SERVER" "$IRC_PORT" | tee -a ircin + ''; + +in out |