1

mycommand每当完成对 SVN 子目录的提交时,我希望我的 SVN 服务器执行特定命令svn-rep/myfolder

我该怎么做?我知道有预装钩子的钩子目录。但是我将如何从中制作自定义钩子?SVN 如何知道何时调用哪个钩子 - 它是基于文件名的吗?并且我将如何限制仅在提交更改某些文件时才执行挂钩svn-rep/myfolder

需要明确的是:该命令永远不会改变,它只是引用位于服务器某处的另一个脚本。

编辑:我刚刚实现post-commit并且出于测试目的,它应该将 SVN 目录的修订号附加到已经存在的(并且每个人都可以写):

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
from subprocess import Popen, PIPE

dirRevisionCmd  = 'svn info /var/www/main | grep -i "Letzte geänderte Rev"

process = Popen(headRevisionCmd, shell=True, stdout=PIPE, stderr=PIPE)
out, err = process.communicate()

with open("/var/lib/svn/rep/hooks/testfile", "a") as testfile:
    testfile.write("err:" + err.strip() + "\n")
    testfile.write("out:" + out.strip() + "\n")

这导致每次提交后标准输出为空:

www-data
err:
out:

如果我post-commit手动执行,“out”行包含一些文本。那么为什么它不适用于 SVN?

4

1 回答 1

6

服务器上的 Subversion 存储库内部是一个名为hooks. 里面是示例钩子脚本。它们都以.tmpl后缀结尾。他们真的是占位符。仅此而已。

如果一个程序或脚本被调用post-commit,Subversion 将在有人提交后执行它。这是可执行文件、Windows Batch 程序还是 Unix shell 脚本都没有关系。Subversion 将在提交发生后执行它。脚本的作用无关紧要。真的就是这么简单。

如果已经有一个名为 的程序post-commit怎么办?你必须修改它。正如我所说,默认存储库中没有钩子——只有一堆模板,你可以根据需要使用它们。如果有一个post-commit程序,那么肯定有人已经添加了它。

因此,只需将您的命令放在hooks目录中,确保它是可执行的,然后调用它post-hook。Subversion 将在有人提交后执行它。


您从未指定要执行的此命令是什么,因此我无法提供任何进一步的建议。但是,通常有一些挂钩脚本的准则:

  1. 挂钩脚本的执行时间不应超过几毫秒。当一个钩子脚本执行时,它会占用提交者的机器,直到钩子脚本完成。例如,一个常见问题是如何通过提交后脚本进行部署。这是一个坏主意,因为它会长时间占用提交者的计算机。有更好的方法来做到这一点。
  2. 挂钩脚本在服务器上运行,提交发生在客户端机器上。这表示:
    1. 钩子脚本无权访问客户端的环境。
    2. 挂钩脚本无法查询客户端。
    3. 挂钩脚本无法修改提交。
    4. 挂钩脚本无法搜索客户端的工作目录。
      • 这也意味着预提交钩子除了接受或拒绝提交之外不能做任何事情。
    5. 挂钩脚本不应导致新的提交。首先是提交钩子的问题,导致提交导致自身在循环中再次运行。其次,它使刚刚提交的人的工作目录过时。另外,这意味着你 50% 的日志历史只是你的提交钩子在自言自语。
  3. 最后,Hook 脚本有一种非常简单的方式与客户端对话:
    1. 挂钩脚本无权访问客户端的STDINSTDOUT. 事实上,钩子脚本无法访问 STDIN 或 STDOUT。
    2. 挂钩脚本通过将退出值设为零来显示成功。他们通过执行除零以外的退出值来显示失败。
    3. 如果钩子以非零值退出,则钩子脚本生成的 STDERR 将被发送到客户端,但不会发送到子进程。这样,您可以向客户端解释挂钩脚本失败的原因。

正如其他人所说:阅读在线的精美手册。它一步一步地处理事情。创建一个测试存储库并使用钩子脚本。它们真的很简单。你可以看看我写的一个post-commit 钩子。它带有安装说明。也许这会有所帮助。


回复

如果我手动执行 post-commit,则“out”行包含一些文本。那么为什么它不适用于 SVN?

我已按列表重新编号以使其成为数字列表。看一下第 3.1 点:钩子脚本无权访问 STDOUT。我不是 Python 程序员,但看起来您正在尝试使用 STDOUT 将输出通过管道传输到另一个进程。挂钩脚本吃掉 STDOUT,并且该输出无法发送到另一个进程。此外,STDERR 被捕获,但不通过管道发送。相反,会收集 STDERR 并将其发送到执行提交的客户端。这样,您可以向客户端发送错误描述。

您可以打开一个子流程并将其发送文本,但不能通过管道。

于 2012-12-03T00:47:16.063 回答