在SVN(Subversion)版本控制系统中,pre-revprop-change 是一个核心的钩子脚本(Hook Script),用于在修改版本属性(Revision Property) 之前触发执行,以实现对属性修改操作的权限控制、合法性校验或日志记录等功能。


1. 核心概念铺垫:版本属性(Revision Property)

要理解 pre-revprop-change,首先需要明确 版本属性 的含义:
SVN 中每个版本(Revision)除了包含代码文件的变更外,还附带一些描述该版本的元数据,这些元数据就是“版本属性”。常见的版本属性包括:

  • svn:log:版本提交时的日志信息(最常用的属性,用户通常会修改旧版本的日志来修正错误描述)。
  • svn:author:该版本的提交者账号。
  • svn:date:该版本的提交时间。

默认情况下,SVN 允许用户通过 svn propsetsvn propedit 等命令修改这些属性(尤其是 svn:log),而 pre-revprop-change 正是为了“拦截”这类修改操作而存在。

2. pre-revprop-change 的核心作用

pre-revprop-change 的本质是一个可执行脚本(通常是 Shell 脚本,Windows 下也可是 Batch 脚本),存储在 SVN 仓库的 hooks 目录中(路径:[仓库根目录]/hooks/pre-revprop-change)。

其核心作用是:在版本属性被实际修改前,检查该修改操作是否合法。具体逻辑由脚本内容定义,常见用途包括:

  • 权限控制:只允许管理员或特定用户修改版本属性(例如禁止普通开发修改 svn:author 或旧版本的 svn:log)。
  • 合法性校验:确保修改后的属性符合规范(例如 svn:log 不能为空、长度不小于 10 个字符)。
  • 日志记录:记录“谁在什么时间尝试修改哪个版本的哪个属性”,便于审计。
  • 直接禁止修改:完全阻断所有版本属性的修改操作(例如严格要求提交日志一旦提交就不能修改)。

3. 工作流程

当用户执行修改版本属性的命令(如 svn propedit svn:log -r 100,表示修改第 100 版本的日志)时,SVN 会按以下流程触发 pre-revprop-change

  1. 用户发起版本属性修改请求。
  2. SVN 自动检测仓库 hooks 目录下是否存在可执行的 pre-revprop-change 脚本。
  3. 若脚本存在,SVN 会将以下关键参数传递给脚本,供脚本判断:
    • [仓库路径]:被操作的 SVN 仓库在服务器上的绝对路径。
    • [版本号]:被修改属性的版本号(如 100)。
    • [用户名]:执行修改操作的用户账号。
    • [属性名]:被修改的版本属性名(如 svn:log)。
    • [操作类型]:属性的修改类型(通常是 M,表示 Modify)。
  4. 脚本执行后,通过退出码告知 SVN 是否允许修改:
    • 退出码 0:校验通过,SVN 继续执行属性修改。
    • 退出码 非 0:校验失败,SVN 立即终止修改操作,并向用户返回脚本输出的错误信息。

4. 默认状态与配置注意事项

(1)默认状态

SVN 仓库初始化时,hooks 目录下会生成一个模板文件 pre-revprop-change.tmpl(而非直接可用的 pre-revprop-change)。模板文件通常包含基础注释和示例逻辑,但默认不生效(因为后缀是 .tmpl,且可能没有可执行权限)。

若未手动配置 pre-revprop-change 脚本,SVN 会允许所有用户修改版本属性(这在生产环境中可能存在风险,例如误改提交者或日志)。

(2)配置步骤(以 Linux 服务器为例)

  1. 进入仓库的 hooks 目录:
    cd /path/to/your/svn/repo/hooks
    
  2. 复制模板文件并移除后缀:
    cp pre-revprop-change.tmpl pre-revprop-change
    
  3. 赋予脚本可执行权限(关键,否则 SVN 无法运行脚本):
    chmod +x pre-revprop-change
    
  4. 编辑脚本,根据需求修改逻辑(例如只允许管理员修改 svn:log)。

5. 常见脚本示例(禁止普通用户修改旧版本日志)

以下是一个简化的 pre-revprop-change 脚本示例,功能为:

  • 只允许用户 admin 修改 svn:log 属性;
  • 禁止修改 svn:authorsvn:date 属性。
#!/bin/sh

# 接收 SVN 传递的参数
REPO="$1"
REV="$2"
USER="$3"
PROPNAME="$4"
ACTION="$5"

# 禁止修改 svn:author 和 svn:date
if [ "$PROPNAME" = "svn:author" ] || [ "$PROPNAME" = "svn:date" ]; then
  echo "Error: 不允许修改 $PROPNAME 属性!" >&2
  exit 1
fi

# 只允许 admin 用户修改 svn:log
if [ "$PROPNAME" = "svn:log" ] && [ "$USER" != "admin" ]; then
  echo "Error: 只有 admin 可以修改版本日志!" >&2
  exit 1
fi

# 校验通过,允许修改
exit 0
@echo off
setlocal

:: 接收 SVN 传递的参数(Windows 中参数通过 %1~%5 接收)
set REPO=%1
set REV=%2
set USER=%3
set PROPNAME=%4
set ACTION=%5

:: 禁止修改 svn:author 和 svn:date
if "%PROPNAME%"=="svn:author" (
  echo Error: 不允许修改 svn:author 属性!1>&2
  exit /b 1
)
if "%PROPNAME%"=="svn:date" (
  echo Error: 不允许修改 svn:date 属性!1>&2
  exit /b 1
)

:: 只允许 admin 用户修改 svn:log
if "%PROPNAME%"=="svn:log" (
  if not "%USER%"=="admin" (
    echo Error: 只有 admin 可以修改版本日志!1>&2
    exit /b 1
  )
)

:: 校验通过,允许修改
exit /b 0

6. 与 post-revprop-change 的区别

SVN 的 hooks 目录中还有一个 post-revprop-change 脚本,容易与 pre-revprop-change 混淆,两者的核心区别在于触发时机

钩子脚本 触发时机 核心作用 能否阻止修改
pre-revprop-change 版本属性修改之前 校验修改合法性、控制权限 能(非 0 退出码)
post-revprop-change 版本属性修改之后 记录修改结果、发送通知(如邮件告警) 不能(仅用于事后处理)

总结

pre-revprop-change 是 SVN 中管控版本属性修改的“守门人”,通过它可以规范团队对提交日志、提交者等元数据的操作,避免非授权修改导致的版本库混乱。在实际使用中,需根据团队规范配置脚本逻辑,并确保脚本具备可执行权限,才能发挥其作用。