diff options
| author | tv <tv@krebsco.de> | 2015-06-18 21:21:54 +0200 | 
|---|---|---|
| committer | tv <tv@krebsco.de> | 2015-06-18 21:21:54 +0200 | 
| commit | 09e2e897b5de39eed3d3c58dffeee421c388e36d (patch) | |
| tree | a69e699db645f20ce436d9cc973dffd317459f96 /lib | |
| parent | 5f868108b5f2ec270ad36ebe60d6c84467c3b356 (diff) | |
lib/git: add irc-announce
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/default.nix | 3 | ||||
| -rw-r--r-- | lib/git.nix | 140 | 
2 files changed, 139 insertions, 4 deletions
| diff --git a/lib/default.nix b/lib/default.nix index 27cf0e2..164a6a1 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,4 +1,4 @@ -{ lib, ... }: +{ lib, pkgs, ... }:  with builtins; @@ -11,6 +11,7 @@ rec {      lib = lib // {        inherit addNames;      }; +    inherit pkgs;    };    addName = name: set: diff --git a/lib/git.nix b/lib/git.nix index 5916cf8..b28d894 100644 --- a/lib/git.nix +++ b/lib/git.nix @@ -1,7 +1,7 @@ -{ lib, ... }: +{ lib, pkgs, ... }:  let -  inherit (lib) addNames; +  inherit (lib) addNames escapeShellArg makeSearchPath;    commands = addNames {      git-receive-pack = {}; @@ -37,5 +37,139 @@ let      master = "refs/heads/master";      all-heads = "refs/heads/*";    }; + +  irc-announce-script = pkgs.writeScript "irc-announce-script" '' +    #! /bin/sh +    set -euf + +    export PATH=${makeSearchPath "bin" (with pkgs; [ +      coreutils +      gawk +      gnused +      netcat +    ])} + +    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 +  ''; + +  hooks = { +    # TODO make this a package? +    irc-announce = { nick, channel, server, port ? 6667 }: '' +      #! /bin/sh +      set -euf + +      export PATH=${makeSearchPath "bin" (with pkgs; [ +        coreutils +        git +        gnused +      ])} + +      nick=${escapeShellArg nick} +      channel=${escapeShellArg channel} +      server=${escapeShellArg server} +      port=${toString port} + +      empty=0000000000000000000000000000000000000000 + +      unset message +      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 $oldrev | cut -b-7) +        id2=$(echo $newrev | cut -b-7) +        if [ $oldrev = $empty ]; then id=$empty_tree; fi +        if [ $newrev = $empty ]; then id2=$empty_tree; fi + +        case $receive_mode in +          create) +            #git log --oneline $id2 +            link="http://cd/cgit/$GIT_SSH_REPO/" +            ;; +          fast-forward|non-fast-forward) +            #git diff --stat $id..$id2 +            link="http://cd/cgit/$GIT_SSH_REPO/diff/?h=$h&id=$id&id2=$id2" +            ;; +        esac + +        #host=$nick +        #$host $GIT_SSH_REPO $ref $link +        message="''${message+$message +      }$GIT_SSH_USER $receive_mode pushed $link" +      done + +      if test -n "''${message-}"; then +        exec ${irc-announce-script} \ +          "$server" \ +          "$port" \ +          "$nick" \ +          "$channel" \ +          "$message" +      fi +    ''; +  }; +  in -commands // receive-modes // permissions // refs +commands // receive-modes // permissions // refs // hooks | 
