2011-12-07 48 views
1

在我工作的公司中,有些項目有一個project.info文件,其中包含程序/庫/當前版本。有沒有辦法檢查一個git標籤是否與相應提交的內容匹配?

實際上,當有人想要標記一個版本時,他必須首先確保project.info文件(它是版本化的)是最新的並且包含與他將要創建的標籤的名稱相同的版本。不需要說這是容易出錯的。

我們在客戶端 - 服務器的工作流程工作的混帳(所有提交到同一個中央資料庫),所以我想知道:有沒有辦法讓這個中央存儲庫拒絕標籤,其中project.info(鉤吧?)不是匹配?

我應該尋找什麼開始?

非常感謝。

+0

爲了讓更多的背景下可能的答案,你需要在「服務器」端完成這項工作,還是可以將它分發到每個客戶端上(也就是說有些人可能決定不遵守)? – Romain

+0

@Romain:這應該由服務器執行。客戶可以在自己的工作站上做任何他們想做的事情,但必須遵守一些準則,以便能夠在中央存儲庫上進行更改。 – ereOn

+0

聽起來像一個'pre-receive'鉤子用例,我不知道該怎麼做是在這個階段檢測'tag'更新(從來沒有這樣做:D) – Romain

回答

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 

而現在它完美的作品:)

0

服務器端

如果你打算使用掛鉤,一個後收到鉤(服務器裁判更新)可能會與project.info變化的承諾,如果它已經被人遺忘,但最初的標記提交將不具有文件中的正確信息...

如果要在更新ref之前驗證此問題,問題是預接收/更新掛鉤實際上沒有檢查所需的信息project.info(th ey獲取正在更新的ref的名稱,存儲在ref中的舊對象名稱以及要存儲在ref中的新對象名稱)。

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

在這個問題上的一些其他堆棧溢出主題:

客戶端

這不能保證任何事情,因爲客戶可以決定不應用適當的方法。儘管如此,提交後掛鉤也許可以做到這一點。

+0

感謝您的建議,我會可能會嘗試用** update **鉤子做些事情。 – ereOn

相關問題