jth*_*h41 6 git git-submodules githooks post-checkout-hook
我有一个post-checkout和后合并githook与这些内容:
#!/bin/bash
# MIT © Sindre Sorhus - sindresorhus.com
set -eux
changed_files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"
check_run() {
echo "$changed_files" | grep --quiet "$1" && eval "$2"
}
echo ''
echo 'running git submodule update --init --recursive if .gitmodules has changed'
check_run .gitmodules "git submodule update --init --recursive"
echo ''
echo 'running npm install if package.json has changed'
check_run package.json "npm prune && npm install"
echo ''
echo 'running npm build:localhost'
npm run build:localhost
Run Code Online (Sandbox Code Playgroud)
奇怪的是,如果.gitmodules没有更改,脚本将结束而不是检查package.json.(它甚至不执行第12行之后的回波线)
删除check_run调用并仅使用直接命令似乎工作正常.
删除check_run .gitmodules "git submodule update --init --recursive"确实有效.但是,下一行中会显示相同的行为:check_run package.json "npm prune && npm install"如果package.json尚未更改
是否有一些我错过的导致check_run结束第一个文件更改未找到的脚本?
的set -e是这里的问题:-e意思是"出口,如果事情失败",其中"失败"被定义为"退出非零".
我们在输出中看到,作为最后几行:
+ check_run .gitmodules 'git submodule update --init --recursive'
+ echo ''
+ grep --quiet .gitmodules
Run Code Online (Sandbox Code Playgroud)
(然后别的什么).脚本退出之后grep --quiet.
这是实际的定义check_run:
check_run() {
echo "$changed_files" | grep --quiet "$1" && eval "$2"
}
Run Code Online (Sandbox Code Playgroud)
这解析左边是哪里,右边是.left && rightecho ... | grep ...eval "$2"
我们看到左侧部分运行而右侧部分没有运行.这里我们需要了解一些关于shell的内容:即使有-eset,如果某些内容失败,它们也不会立即退出,只要该内容是测试的一部分.1 所以这不是问题所在.
但它仍然是问题所在,因为它的退出状态是它运行的最后一件事的退出状态.它最后运行的是左侧管道,它是.管道的退出状态是它的最后一个组件,退出状态2即.如果grep找到字符串(并且同时抑制其输出),则grep退出零;如果不找到,则返回1;对于一般错误,grep退出2,因此退出状态为1.left && rightecho ... | grep ...grep--quiet
因此,退出状态也是1.left && right
因此,既然-e有效,外壳退出了!
治愈要么是为了避免-e(但这意味着如果其他东西意外失效,外壳犁,这可能有点危险),或确保不会使外壳退出.left && right
有一种直接的方法来做后者:替换为:left && rightif left; then right; fi
if echo "$changed_files" | grep --quiet "$1"; then
eval "$2"
fi
Run Code Online (Sandbox Code Playgroud)
请注意,如果eval "$2"失败,shell仍将退出.
有一种不同的,稍微有点棘手的方法来做一个不同的效果:替换为."和"表达式绑定得更紧密,因此这意味着:left && rightleft && right || true
&&失败(左侧退出非零,或右侧运行且右侧退出非零),则评估|| true退出0 的零件.因此:
echo "$changed_files" | grep --quiet "$1" && eval "$2" || true
Run Code Online (Sandbox Code Playgroud)
总是以0,eval-ing "$2"当且仅当左侧的失败(没有找到grepped-表达).
如果check_run即使eval "$2"失败也要继续,请使用second(|| true)版本.如果你想check_run停止(并且让整个shell退出),-e如果eval "$2"失败,请使用first(if ...; then)版本.
1真正的古4BSD /bin/sh,很久以前它去开源,有一个bug:-e 会令在这些情况下壳退出.(我想我曾经自己修过一个,但是当4BSD进入一个新的时候,不是基于史蒂夫伯恩的原始代码,那个错误就不存在了.)
2在bash中,您可以更详细地控制它.特别是,您可以获取数组变量中管道的每个组件的状态$PIPESTATUS.
| 归档时间: |
|
| 查看次数: |
94 次 |
| 最近记录: |