【问题标题】:Chaining git hooks链接 git 钩子
【发布时间】:2012-02-02 13:40:29
【问题描述】:

你们中的许多人可能都知道,git 中只能有一种钩子类型。 如果需要评估两个更新挂钩。 git 管理员有两个无法管理的解决方案:

  1. 将挂钩脚本合并在一起
  2. 使用exec 手动链接它们

我正在寻找一个优雅的解决方案(用 BASH 编写),类似于文件夹 hooks/update.dhooks/post-receive.d,这将允许挂钩评估的松散耦合。一旦钩子失败,链接应该立即停止。

我实际上在这个 URL http://blog.bluefeet.net/2011/08/chained-git-hooks 找到了一个用 perl 编写的可接受的解决方案

问题:我的服务器运行不同版本的 perl,我得到 perllib 版本不匹配。它失败了。

【问题讨论】:

  • 相关答案:stackoverflow.com/a/3464399/119963 重点是跟踪钩子,而不是链接它们,但链接基本上是一个微不足道的扩展:围绕钩子执行包裹一个循环(例如for hook in hooks/update.d/*; do ...)跨度>
  • 感谢您的指点,它帮助了

标签: git githooks


【解决方案1】:

经过进一步调查和测试,这是一个可行的解决方案:

创建文件.git/hooks/hook-chain如下

#!/bin/bash
#
# author: orefalo

hookname=`basename $0`


FILE=`mktemp`
trap 'rm -f $FILE' EXIT
cat - > $FILE

for hook in $GIT_DIR/hooks/$hookname.*
do
    if test -x "$hook"; then
#       echo $hook
        cat $FILE | $hook "$@"
        status=$?

        if test $status -ne 0; then
            echo Hook $hook failed with error code $status
            exit $status
        fi
    fi
done

现在链接任何需要链接的钩子,例如

  • ln -s 钩链更新
  • ln -s hook-chain post-receive

最后,通过将它们重命名为hookname.action来创建链

 -rwxr-xr-x. 1 git  git  6710  functions
 -rwxr-xr-x. 1 git  git   280  hook-chain
 -rwxr-xr-x. 1 git  git  1524  post-mirror
 lrwxrwxrwx. 1 root root   10  post-receive -> hook-chain
 -rwxr-xr-x. 1 git  git  8763  post-receive.1email
 -rwxr-xr-x. 1 git  git  1745  post-receive.2github
 -rwxr-xr-x. 1 git  git   473  post-upload-pack
 -rwxr-xr-x. 1 git  git   346  pre-receive
 lrwxrwxrwx. 1 root root   10  update -> hook-chain
 -rwxr-xr-x. 1 git  git  2975  update.1acl
 -rwxr-xr-x. 1 git  git   328  update.2github

例如,在上面的示例中,update hook 将运行 update.1acl,然后运行 ​​update.2github

post-receive 钩子,运行 post-receive.1email 后跟 post-receive.2github

【讨论】:

  • 这不是一个代码审查网站,但是....与其明确删除 tmpfile,不如通过在调用 mktemp 之前添加以下行来自动删除它:trap 'rm -f $FILE '0
  • this mail 中,而不是临时文件,有人使用data=$(cat) 然后echo "$data" | "$hook"
  • 我有基于the mail I mentioneda version of this script。主要的区别是我的 all 在退出之前运行了钩子,所以如果你选择绕过钩子,你确切地知道你正在跳过什么。
  • 我喜欢你的版本,请发布完整的解决方案作为答案。
【解决方案2】:

对于那些不愿意点击 cmets below other answer 中的每个链接的人,这里是 @HenrikN 的 the script 的几乎未经修改的版本:

#!/bin/bash

# Runs all executable hookname-* hooks and exits after,
# if any of them was not successful.
#
# Based on
# http://osdir.com/ml/git/2009-01/msg00308.html

data=$(cat)
exitcodes=()
hookname=$(basename $0)

# Run each hook, passing through STDIN and storing the exit code.
# We don't want to bail at the first failure, as the user might
# then bypass the hooks without knowing about additional issues.

for hook in $GIT_DIR/hooks/$hookname-*; do
  test -x "$hook" || continue
  echo "$data" | "$hook"
  exitcodes+=($?)
done

# If any exit code isn't 0, bail.

for i in "${exitcodes[@]}"; do
  [ "$i" == 0 ] || exit $i
done

【讨论】:

    【解决方案3】:

    我根据 OP 和 Olivier Refalo 的帖子创建了一个 shell 脚本(做了一些修改):

    https://gist.github.com/amirbawab/e9f42ef8d441316707d9b90777e5718b

    该脚本将生成一个钩子文件,该文件将在$hook_file_name.d/$hook_file_name.*内执行脚本

    例如:对于commit-msg钩子,脚本将在.git/hooks下生成commit-msg文件,该文件将执行commit-msg.d/下的所有脚本。

    commit-msg.d 下的文件应与 commit-msg.* 模式匹配,以允许将辅助 shell 文件放置在这些文件夹中而不执行它们。

    脚本使用:./extend_git_hooks.sh [REPO_PATH]

    【讨论】:

      猜你喜欢
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      • 2012-11-04
      • 2019-09-21
      • 1970-01-01
      • 2013-07-17
      • 2011-01-04
      • 2011-05-10
      相关资源
      最近更新 更多