Subversion Hooks
时间:2010-03-14 来源:sophia_wang99
- Subversion Hooks
- 前言
- Subversion 被视为 CVS 的替代者
- 它改进了 CVS 恼人的文件名、目录名修改等多个 CVS 的痼疾
- 它最大限度的保持了和 CVS 的一致,照顾了 CVS 的使用习惯
- Subversion 也支持扩展,成为 Hooks(钩子脚本),类似于 CVS 的 CVSROOT 脚本扩展
- CVSROOT 脚本扩展可以参见 WHODO 的这篇文章
- 《CVS Howto》
- CVSROOT 脚本扩展可以参见 WHODO 的这篇文章
- WHODO 项目采用 Subversion 作为版本控制系统。本文介绍了 WHODO SVN 的 Hooks 定制
- 本文的 Hooks 脚本仅在 svn 1.1.4 和 svn 1.3.1 上进行过测试。
- Subversion 被视为 CVS 的替代者
- Hooks 定制的注意事项
- 1. 权限:脚本是否具有可执行权限?
- chmod a+rx
- 2. 不要依赖系统的环境变量,尤其是 PATH
- 为安全计,svn 执行脚本的环境变量为空
- 命令使用绝对路径,或者定义 PATH 环境
- 3. 并不是 STDERR 输出都返回控制台!
- 不要认为输出到 stderr 的错误信息都输出
- 只有 Hooks 运行失败,才将 STDERR 的输出传给 SVN 客户端
- 4. DOS 格式还是 Unix 格式?
- 还有经常犯的一个错误是上传了 DOS 格式的脚本到 Linux/Unix 服务器
- Linux 上可以用 dos2unix 命令将 DOS 换行符 0D0A 转换为 0A
- 5. pre-revprop-change 和 post-revprop-change
- pre-commit, post-commit 脚本,只有 pre-commit 的返回值被检查,post-commit 即便运行错误,也不影响提交
- 但 pre-revprop-change 和 post-revprop-change 这两个脚本任何一个脚本错误,都导致对 revision 的属性修改失败。(实现似乎和手册中有出入)
- 1. 权限:脚本是否具有可执行权限?
- SVN Hooks 介绍
- SVN Hooks 的位置
- 位于 Repository 的 hooks 目录下
- 每一个 Repository 对应一个 hooks 目录
- SVN Hooks 名称
- SVN 1.3 有 9 个 Hooks 脚本,SVN Repository 刚刚配置完成,所有的 hooks 脚本以 .tmpl 扩展名存在。若要启用某个 hooks,去掉其 .tmpl 扩展名
- $ ls repos/hooks/ post-commit.tmpl post-unlock.tmpl pre-revprop-change.tmpl post-lock.tmpl pre-commit.tmpl pre-unlock.tmpl post-revprop-change.tmpl pre-lock.tmpl start-commit.tmpl
- Windows:Windows 上是根据扩展名判断可执行文件的,因此需要有扩展名,可以为 .exe 或 .bat
- 依赖的第三方软件
- CPAN
- Config::IniFiles
- svn 的 SWIG python binding
- 测试是否已经正确安装
- >>> import sys >>> print sys.path >>> from svn import *
- 安装
- SWIG
- Subversion
- make swig-py && make install-swig-py
- 测试是否已经正确安装
- CPAN
- 下面分别介绍各个脚本以及可行的定制方案。脚本参见 hooks 目录。
- 由于 Web 服务器限制,有的脚本可能无法从 web 直接下载。可以从 Whodo SVN 版本控制系统中下载。
- SVN Hooks 的位置
- start-commit
- 说明
- 在客户端还没有向服务器提交数据之前,即还没有建立 Subversion transaction(缩写为 txn) 之前,执行执行该脚本
- 因此该脚本可以很快执行,不像其他 pre-commit, post-commit 脚本要等到数据传输完成之后才执行。
- 也因此,该脚本获取的信息有限,不堪大用
- 参数
- [1] REPOS-PATH (the path to this repository)
- [2] USER (the authenticated user attempting to commit)
- 定制:暂时关闭提交功能
- 如果 hooks 目录中存在文件 COMMIT_LOCK ,则暂时终止提交
- 代码示例
- #!/bin/sh REPOS="$1" USER="$2" TOOLS_DIR=$REPOS/hooks/scripts LOCK_FILE=$REPOS/hooks/COMMIT_LOCK if [ -f $LOCK_FILE ]; then if [ -s $LOCK_FILE ]; then # Characters in LOCK_FILE should be utf-8 format! cat $LOCK_FILE >&2 else # echo "系统维护中,暂时禁止提交。" >&2 echo "Under maintenance, commit not allowed this time." >&2 fi exit 1 fi
- 定制:用户黑名单
- 如果 hooks 目录中存在 BLACK_LIST 文件,列在其中的用户,禁止提交
- 代码示例
- BLACKLIST_FILE=$REPOS/hooks/BLACK_LIST # check black_list if [ -s $BLACKLIST_FILE ]; then ( grep -v "^#" "$BLACKLIST_FILE" | grep -iwq "$USER" ) && \ echo "$USER is not allowed to commit." >&2 && exit 1 fi
- 定制:禁止未登录用户提交
- 不过 SVN 的身份验证仅在需要时提供,因此好像此定制未必有效?
- 代码示例
- #!/bin/sh REPOS="$1" USER="$2" if [ "x$USER" = "x" ]; then echo "You must login before you can commit." 1>&2 exit 1 fi
- 定制:简陋的权限控制示例
- 一般不在 start-commit 中进行访问控制,因为只能限制到 repository 一级,不能精细到 repository 内部的目录、文件,因此基本没有用处。
- 代码示例
- case $REPOS in /opt/svnhome/test) case $USER in jiangxin) exit 0 ;; *) echo "User: $USER not allowed" >&2 exit 1 ;; esac ;; *) echo "$REPOS is unchangeable for $USER" >&2 exit 1 ;; esac
- 定制:检查 Repository 容量限制
- 参考: http://www.toutprogrammer.com/article_29_3.html
- 代码示例
- #!/bin/sh # 参考: http://www.toutprogrammer.com/article_29_3.html PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:$PATH REPOS="$1" USER="$2" MAX_SIZE=20480 # 20MB repos_size=`du -s $REPOS | cut -f 1` if [ $repos_size -gt $MAX_SIZE ]; then echo "Repositroy $REPOS has exceeded maximum size: $MAX_SIZE" 1>&2 exit 1 fi exit 0
- 说明
- pre-commit
- 说明
- 在 Subversion transaction 完毕之后,在提交之前,执行该脚本
- 用 svnlook 可以查看 transaction 中包含的用户信息、提交信息等,具体参见 svnlook 命令帮助
- 用途
- 检查 commit log 格式是否符合规范
- 精细的“写权限”检查。如果是限制对 repos 的读取,需要使用 mod_authz_svn 模块!
- 参数
- [1] REPOS-PATH (the path to this repository)
- [2] TXN-NAME (the name of the txn about to be committed)
- 定制:检查 Commit Log 长度
- bash
- PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:$PATH REPOS="$1" TXN="$2" TOOLS_DIR=$REPOS/hooks/scripts # Make sure that the log message contains some text. SVNLOOK=/usr/local/bin/svnlook commitlog=`$SVNLOOK log -t "$TXN" "$REPOS"` case `echo -n ${commitlog}|wc -c` in 0) echo "Commit log is blank, please write a comment for your commit." >&2 exit 1 ;; [1-2]) echo "Commit log must greater than 2 characters." >&2 exit 1 ;; *) ;; esac
- python
- 因为我经常偷懒,输入一排相同字符(如 .............)当作 commit log
- def check_strlen(log_msg, minLen): log_length = len(log_msg) if log_length > 0: char = log_msg[0] char2= log_msg[-1] idx=1 while idx < len(log_msg): if char == -1 and char2 == -1 and log_length <= 0: break if (char == log_msg[idx]) and (char != -1): log_length = log_length - 1 char = log_msg[idx] else: char = -1 if (char2 == log_msg[-idx]) and (char2 != -1): log_length = log_length - 1 char2 = log_msg[-idx] else: char2 = -1 idx = idx + 1 if log_length < minLen: sys.stderr.write ("Commit log must greater than %d characters, or too simple.\n" % minLen) sys.exit(1)
- bash
- 定制:检查 Commit Log 内容
- python
- def check_pattern(log_msg): patterns = [ #r'(issue\s*[#]?[0-9]+)|(new.*:)|(bugfix:)', ] for pat in patterns: if re.compile(pat, re.I).search(log_msg, 1): continue else: sys.stderr.write ("Cannot find pattern: '%s' in commit log.\n" % pat) sys.exit(1)
- python
- 定制:检查是否有同名(大小写不同)文件存在
- 如果服务器 repository 中存在文件名只是在大小写上有区分的文件,这在 Unix/Linux 上没有问题。但是当客户端为 Windows 时,将会造成各种古怪的现象。此扩展用于 检查 Repository 是否有同名文件(只是大小写不同而已),如果检查到,作为冲突报错。
- perl 实现
- 脚本 check-case-insensitive.pl
- 对于 svn 1.1.x 需要使用 perl 的实现,直接调用 svnlook 命令行
- python 实现
- check-case-insensitive.py
- 定制:检查新增文件的 svn:mime-type,以及 svn:eol-style 设置
- check-mime-type.pl
- check-mime-type.py
- 根据 check-mime-type.pl 改写,主要是为了移植到 Windows 平台
- 定制:检查用户权限
- perl
- 脚本 commit-access-control.pl
- 配置文件 commit-access-control.cfg
- 说明
- INI 格式
- 后面的覆盖前面的权限
- 每一节必须包含 match 关键字
- match = PERL_REGEX
- 每一节必须包含 access 关键字
- access = (read-only|read-write)
- 可选的 users 关键字
- 如果没有 users 关键字,则针对所有用户
- 可以在一行写下多个用户名,用空格分隔
- users = username1 [username2 [username3 [username4 ...]]]
- 也可以多条 users 语句
- users = username1 [username2] users = username3 username4
- INI 格式
- 示例
- [Make everything read-only for all users] match = .* access = read-only [Make project1 read-write for users Jane and Joe] match = ^(branches|tags|trunk)/project1 users = jane joe access = read-write [However, we don't trust Joe with project1's Makefile] match = ^(branches|tags|trunk)/project1/Makefile users = joe access = read-only
- 说明
- 缺点
- ACL 控制功能没有下面的 python 脚本全面
- 没有用户分组设置
- python
- 脚本 svnperms.py
- 配置文件 svnperms.conf
- 配置
- 一个配置文件可以被多个 Repository 共享
- 定制用户组
- 可以包含多个 groups 节
- [groups] group1 = user1 user2
- 还可以包含只对 repository 有效的用户组
- [repos_basename groups] group2 = user5 user6
- 引用用户组时,前面加上一个 @ 符号,用以和 用户名 区分
- 可以包含多个 groups 节
- 每个 repository 有一个 Section 与之对应
- section 的名称默认为 repository 的 basename,即去掉前面目录部分
- Section 中的权限策略由 KV 对组成
- KV 对的 KEY 由常规表达式组成,和修改的文件路径匹配
- KV 对的 Value 定义用户访问控制。用户访问控制可以是多条访问控制策略用空格分开
- 访问控制策略格式: 用户列表(权限列表)
- 用户列表是逗号分开的用户或用户组
- 用户列表为 * 则代表所有用户
- 权限列表是用逗号分隔的权限组合组成
- 三种权限
- add
- 增加权限
- remove
- 删除权限
- update
- 修改文件以及修改属性权限
- add
- Section 之间可以继承
- 如
- [example5 extends example2] releases/[^/]+/ = *(add)
- 如
- perl
- 说明
- post-commit
- 说明
- 在提交之后,执行该脚本。提交已经完成,不可更改,因此本脚本的返回值被忽略
- 该脚本一般用于外发邮件
- 参数
- [1] REPOS-PATH (the path to this repository)
- [2] REV (the number of the revision just committed)
- 定制:发送邮件
- perl
- commit-email.pl 脚本
- 语法: commit-email.pl REPOS REVNUM [[-m regex] [options] [email_addr ...]] ...
- 对于单个项目
- 单个项目,可以用简化的命令行语法
- commit-email.pl REPOS REVNUM [email_addr ...]
- 单个项目有一个默认的配置项组。-m 匹配所有路径
- 同时支持多个项目
- 多个 -m 参数,形成多个配置项组: -m pattern --from EMAIL -s subject EMAIL_ADDR
- commit-email.pl REPOS REVNUM \ -m pattern --from EMAIL -s subject EMAIL_ADDR \ -m pattern --from EMAIL -s subject EMAIL_ADDR \ -m pattern --from EMAIL -s subject EMAIL_ADDR
- 示例
- commit-email.pl -m "^(trunk|branches|tags)/project1" -
- commit-email.pl "$REPOS" "$REV" [email protected]
- commit-email.pl 脚本
- python
- mailer.py
- 配置文件 mailer.conf
- perl
- 定制:与 Bugtracking 系统整合
- 说明
- pre-revprop-change
- 说明
- 在修改 revision 属性之前,执行该脚本
- 如果该脚本不存在,或者该脚本返回 false,则不进行修改 revision 属性操作
- 因为 revision 的属性是没有版本控制的,因此脚本最好提供一个备份的机制
- 参数
- [1] REPOS-PATH (the path to this repository)
- [2] REVISION (the revision being tweaked)
- [3] USER (the username of the person tweaking the property)
- [4] PROPNAME (the property being set on the revision)
- 定制:只允许修改 svn:log,不允许修改其他属性(如 svn:author)
- if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi echo "Changing revision properties other than svn:log is prohibited" >&2 exit 1
- 说明
- post-revprop-change
- 说明
- 在修改 revision 属性之后,执行该脚本。因为修改稿已经完成,不可更改,因此本脚本的返回值被忽略(不过实际上的实现似乎是该脚本的正确执行与否影响属性修改)
- 一般用于触发邮件通知
- 参数
- [1] REPOS-PATH (the path to this repository)
- [2] REV (the revision that was tweaked)
- [3] USER (the username of the person tweaking the property)
- [4] PROPNAME (the property being set on the revision)
- 定制:发送邮件
- perl
- propchange-email.pl
- 语法: propchange-email.pl REPOS REVNUM USER PROPNAME [[-m regex] [options] [email_addr ...]] ...
- 对于单个项目
- 单个项目,可以用简化的命令行语法
- propchange-email.pl REPOS REVNUM USER PROPNAME [email_addr ...]
- 单个项目有一个默认的配置项组。-m 匹配所有路径
- 同时支持多个项目
- 多个 -m 参数,形成多个配置项组: -m pattern --from EMAIL -s subject EMAIL_ADDR
- propchange-email.pl REPOS REVNUM USER PROPNAME \ -m pattern --from EMAIL -s subject EMAIL_ADDR \ -m pattern --from EMAIL -s subject EMAIL_ADDR \ -m pattern --from EMAIL -s subject EMAIL_ADDR
- propchange-email.pl
- perl
- 说明
- pre-lock
- 说明:对文件进行加锁操作之前
- 定制:检查已经存在的 lock 的属主,如果是本人,允许 lock
- post-lock
- 说明:对文件进行加锁操作之后
- pre-unlock
- 说明:对文件进行解锁操作之前
- 定制:检查已经存在的 lock 的属主,如果是本人,允许 lock
- post-unlock
- 说明:对文件进行解锁操作之后
- Windows 平台上的 Subversion Hooks
- 说明
- Windows 上的可执行程序是依据扩展名识别的,因此 Hooks 脚本需要带扩展名。如 pre-commit.bat, 或者 pre-commit.exe
- Windows 平台的 SVN Hooks,仍然沿用了 Unix 的脚本,因而需要安装 Perl, Python 等软件
- 更多的采用 Python 脚本,因为一些 Perl 脚本用到了命令管道等没有移植到 Windows 平台的 Perl Feature。
- pre-commit.bat
- 定制:检查 Commit Log 长度
- commit_log_check.py
- 定制:检查 Commit Log 内容
- commit_log_check.py
- 定制:检查新增文件的 svn:mime-type,以及 svn:eol-style 设置
- check-mime-type.py
- 定制:检查 Commit Log 长度
- pre-revprop-change.bat
- 定制:只允许修改 svn:log,不允许修改其他属性(如 svn:author)
- 尚未实现功能
- 由于 subversion 的 Python Binding 在 Windows 平台的移植的困难,很多用到 svn python 模块的脚本没有移植。可以考虑将依赖 subversion python binding 的脚本用 svnlook 重写。
- 邮件:可以考虑使用 Cygwin 的 exim, ssmtp 等替代 脚本中的 sendmail
- 说明
- 关于本文
- 作者
- J
- Jiang Xin
- 等待你的加入...
- J
- 版本
- 0.2, 2006/5/8
- 增加 Windows 上的 SVN Hooks 脚本;
- 0.1
- 0.2, 2006/5/8
- 参考资料
- 《Version Control with Subversion》
- 作者
- 前言
相关阅读 更多 +