关于FreeBSD的CVSROOT的配置

钩子事务脚本使用简述

1. CVSROOT中的专用设置

1.1. ACL的配置

FreeBSD通过一组shell和Perl脚本来实现ACL。其中用户可配置的是avail和一组文件。avail提供了针对目录的commit权限控制,并支持用户组。

avail文件的格式是(BNF):

   行 ::= 授权<换行符>
  授权 ::= 组|允许|禁止|注释
   组 ::= 'group|'组名'|'成员
  成员 ::= (用户名,|'!'文件名,)*用户名|'!'文件名
  允许 ::= 'avail|'[授权实体['|'目录]]
  禁止 ::= 'unavail|'[授权实体['|'目录]]
授权实体 ::= ':'组名|一组用户
一组用户 ::= (用户名,)*用户名
  注释 ::= '#'注释内容

用户名、组名、文件名、目录均按Unix标准。注释内容可以为除换行之外的任意字符的Kleene闭包。

示范文件:

# Sample 

group|meisters|delphij

# Pick up the list of bad users from ncvs/CVSROOT/badcommitters  See that
# file for details
group|penaltybox|!badcommitters,!badcommitters.global

# Only committers listed in access is allowed to commit
group|committers|!access,!access.master

unavail
avail|:meisters|CVSROOT
avail|:committers|src
avail|:meisters
unavail|:penaltybox

上述内容的意义: meisters组的成员为delphij penaltybox组的内容来自badcommitters和badcommitters.global两个文件 committers组的内容来自access和access.master 不允许未获授权的任何其他操作。 允许meisters写CVSROOT 允许committers写src 允许meisters写任何文件(用于必要时清理) 不允许penaltybox组写任何文件

注意:所有在avail中引用的文件必须列入checkoutlist,否则将无法读取或同步。

1.2. commit mail的配置

commit mail的配置包括几方面:收件人、diff的发送方式。这些都需要在cfg_local.pm中进行配置。

$CHECK_HEADERS:

1.3. 如何限制tag的使用

cvs认为tag操作是一种“特权”(因为这可能影响到发行版本和STABLE版本的品质),FreeBSD对此限制更为严格,其CVSROOT可以提供对tag和对branch commit的限制。

由于这类限制会非常少(过多会影响开发),因此FreeBSD采用了两级控制措施:

  • 基于tag的限制。这类限制是强制的,即只允许少量的开发人员(例如Release Engineer)打符合某种模式的tag,或创建某些branch
  • 基于branch的限制。这类限制是软性的,其目的是实现代码冻结,也就是某个branch只允许经过审批的commit进入,其标志为Approved by: xxx

先说第一种限制。

第一种限制是通过CVS的taginfo HOOK实现的,要达到此一目的,需要在taginfo中加入类似下面的配置: ALL                    $CVSROOT/CVSROOT/tagcheck

而tagcheck则是需要在checkoutlist中申明的一个脚本,其功能是告诉cvs是否应允许完成某一tag操作。具体而言,如果这个脚本返回0,则说明允许,反之则不允许。

下面是一个例子:

#! /bin/sh (-)
#
# $FreeBSD: CVSROOT-doc/tagcheck,v 1.10 2003/01/10 03:05:43 kris Exp $
# $Phantasm: CVSROOT/tagcheck,v 1.3 2004/05/02 12:36:32 delphij Exp $

# TAG  add/mov/del  repo  files...
# $1   $2           $3    $4   ...

case "$1" in
  RELENG*)
    ;;
  RELEASE*)
    ;;
  *)
    exit 0      # not reserved, ok.
    ;;
esac

USER=`/usr/bin/id -un`
case "$USER" in
  delphij)
    exit 0      # ok
    ;;
  *)
    echo "$USER does not have permission to perform this tag operation!" 1>&2
    echo "RELENG* tag operations are reserved for release engineering!" 1>&2
    echo "RELEASE* tag operations are reserved for portmgr and doceng!" 1>&2
    echo "Use 'cvs add' or 'cvs rm' to add/remove files from branches!" 1>&2
    echo "$*" | /usr/bin/mail -s "NCVS TAG" cvs
    exit 1
    ;;
esac

上述脚本的逻辑是:如果给定的tag不匹配RELEASE*或RELENG*的模式,则允许;反之,则判断当前用户身份,并决定是否允许。如果不允许,则会在CVS的返回信息中给出提示,并且给cvs@本机发送一封邮件说明这一情况。

接下来说说如何限制branch。

1.4. 限制branch

对branch的限制的实现,是通过verifymsg,verifymsgcheck,approvecheck,approvers四个文件。具体而言,是利用了CVS的verifymsg HOOK来检查commit log的正确性。这部分脚本的逻辑比较复杂,因此配置起来就非常简单,方法是修改approvers这个文件,其格式是:

路径模式 branch模式 许可的approver模式

例如:

^src/         RELENG_5_[012]  (security-officer|so)

表示:对于所有以src/开头的文件,检查其branch是否属于RELENG_5_0, RELENG_5_1, RELENG_5_2之一,如果是,则检查是否包含:

Approved by: security-officer

或者:

Approved by: so

当然,是否写Approved by: security-officer之前确实得到了这些人的批准是要靠自觉的。


-- delphij (2005-05-27)