有没有办法检查git标签是否与相应提交的内容匹配?

时间:2011-12-07 15:42:08

标签: git hook githooks

在我工作的公司中,一些项目有一个project.info文件,其中包含程序/库/当前版本的任何内容。

实际上,当有人想要标记版本时,他必须首先确保project.info文件(版本化版本)是最新的并且包含与他所关注的标记名称相同的版本创造。不必说这很容易出错。

我们为git工作的客户端 - 服务器工作流程(所有提交都转到同一个中央存储库)所以我想知道:有没有办法(可能是一个钩子?)使这个中央存储库拒绝{{1 } 匹配?

我应该寻找什么才能开始?

非常感谢。

2 个答案:

答案 0 :(得分:2)

感谢这里的所有建议,我成功了。

这是我的最终update钩子脚本:

#!/bin/sh
#
# An example hook script to blocks unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
#   This boolean sets whether unannotated tags will be allowed into the
#   repository.  By default they won't be.
# hooks.allowdeletetag
#   This boolean sets whether deleting tags will be allowed in the
#   repository.  By default they won't be.
# hooks.allowmodifytag
#   This boolean sets whether a tag may be modified after creation. By default
#   it won't be.
# hooks.allowdeletebranch
#   This boolean sets whether deleting branches will be allowed in the
#   repository.  By default they won't be.
# hooks.denycreatebranch
#   This boolean sets whether remotely creating branches will be denied
#   in the repository.  By default this is allowed.
#

# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"

# --- Safety check
if [ -z "$GIT_DIR" ]; then
    echo "Don't run this script from the command line." >&2
    echo " (if you want, you could supply GIT_DIR then run" >&2
    echo "  $0 <ref> <oldrev> <newrev>)" >&2
    exit 1
fi

if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
    echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
    exit 1
fi

# --- Config
allowunannotated=$(git config --bool hooks.allowunannotated)
allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
denycreatebranch=$(git config --bool hooks.denycreatebranch)
allowdeletetag=$(git config --bool hooks.allowdeletetag)
allowmodifytag=$(git config --bool hooks.allowmodifytag)
allowwildtag=$(git config --bool hooks.allowwildtag)
allowunmatchedtag=$(git config --bool hooks.allowunmatchedtag)

# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
    echo "*** Project description file hasn't been set" >&2
    exit 1
    ;;
esac

# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
    newrev_type=delete
else
    newrev_type=$(git cat-file -t $newrev)
fi

case "$refname","$newrev_type" in
    refs/tags/*,commit)
        # un-annotated tag
        short_refname=${refname##refs/tags/}
        if [ "$allowunannotated" != "true" ]; then
            echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
            echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
            exit 1
        fi
        ;;
    refs/tags/*,delete)
        # delete tag
        if [ "$allowdeletetag" != "true" ]; then
            echo "*** Deleting a tag is not allowed in this repository" >&2
            exit 1
        fi
        ;;
    refs/tags/*,tag)
        # annotated tag
        if [ "$allowwildtag" != "true" ] && ./hooks/check_tag -r $refname > /dev/null 2>&1
        then
            echo "*** Tag '$refname' does not match the naming constraints." >&2
            echo "*** Tags must follow the 'x.y-z' pattern, where x, y, and z are numeric characters." >&2
            exit 1
        fi
        if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
        then
            echo "*** Tag '$refname' already exists." >&2
            echo "*** Modifying a tag is not allowed in this repository." >&2
            exit 1
        fi
        if [ "$allowunmatchedtag" != "true" ] 
        then
            project_version=`./hooks/extract_project_version $newrev 2>/dev/null`

            if [ "$project_version" == "" ]
            then
                # We dont output anything in case of success
                #echo "*** Project does not contain a project.info file. No tag match performed."
                :
            elif [ "$project_version" == "error" ]
            then
                # The project contains an invalid project.info: we accept the tag but warn about it.
                echo "*** Project contains an invalid project.info file. No tag match performed."
            else
                tag_version=${refname##refs/tags/}

                if [ "$project_version" != "$tag_version" ]
                then
                    echo "*** Tag and project version do not match: $tag_version != $project_version"
                    echo "*** Please check your project.info file."
                    exit 1
                fi
            fi
        fi
        ;;
    refs/heads/*,commit)
        # branch
        if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
            echo "*** Creating a branch is not allowed in this repository" >&2
            exit 1
        fi
        ;;
    refs/heads/*,delete)
        # delete branch
        if [ "$allowdeletebranch" != "true" ]; then
            echo "*** Deleting a branch is not allowed in this repository" >&2
            exit 1
        fi
        ;;
    refs/remotes/*,commit)
        # tracking branch
        ;;
    refs/remotes/*,delete)
        # delete tracking branch
        if [ "$allowdeletebranch" != "true" ]; then
            echo "*** Deleting a tracking branch is not allowed in this repository" >&2
            exit 1
        fi
        ;;
    *)
        # Anything else (is there anything else?)
        echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
        exit 1
        ;;
esac

# --- Finished
exit 0

这是我的extract_project_version脚本:

#!/bin/bash

rev=$1

if [ "$rev" == "" ]
then
    echo "Missing revision parameter." >&2
    exit 1
fi

tmpdir=/tmp/$$.extract_project_version

mkdir -p $tmpdir
git archive $rev | tar -x -C $tmpdir

if [ -e "$tmpdir/project.info" ]
then
    echo $tmpdir/project.info
fi

rm -rf $tmpdir

现在它完美无缺:)

答案 1 :(得分:0)

服务器侧

如果您计划使用挂钩,收件后挂钩(服务器引用更新)可能会创建一个提交project.info如果已被遗忘,但初始标记commit在文件中没有正确的信息......

如果您想在更新引用之前验证这一点,问题是预接收/更新挂钩实际上并不具备检查project.info有效性所需的信息(它们获取要更新的ref的名称,存储在ref中的旧对象名称以及要存储在ref中的新对象名称。

您可以找到some examples of hooks heresome information there

关于此主题的其他一些Stack Overflow主题:

<强>客户端

这不能确保任何事情,因为客户可以决定不应用适当的方法。不过,提交后挂钩可能会成功。