【问题标题】:How to implement SVN pre-commit hook with best performance?如何以最佳性能实现 SVN 预提交钩子?
【发布时间】:2011-01-04 06:53:08
【问题描述】:

我们有以下工具:

  • Subversion(1.5.9 版)
  • Polarion(版本 3.2.2)

Polarion 基于 Subversion,因此在更改任何内容的每个操作(通常是这种情况)上,Polarion 将使用 Subversion 提交来更改任何内容。目前所有的东西都存储在一个且只有一个存储库中,因此每个用户的每次提交(同一个存储库中的大约 100-200 个)都会触发预提交挂钩。

那么提供预提交钩子的最佳策略是什么

  • 仅触发部分项目,而非所有项目
  • 尽可能快地运行,因为每个预提交挂钩都会阻止所有其他提交。

我们尝试使用 Java 实现预提交挂钩(使用 SVNKit),但这将在每次提交 Java VM 时开始。那么有什么想法可以很好地实现吗?

【问题讨论】:

    标签: svn pre-commit-hook


    【解决方案1】:

    您能做的最好的事情就是停止使用一个存储库来处理所有事情。

    除了更好的性能之外,这将使您能够对您的存储库进行细粒度控制,允许您拥有单独的访问控制、每个存储库(项目)的单独挂钩等。

    【讨论】:

    • 我们当然愿意这样做,但是在当前版本的 Polarion 中,我们失去了将 Polarion 中的工作项与正在处理的修订自动链接的可能性。这可能会在 2010 年推出的下一个版本中实现,但目前还不行。
    • 您可以添加一个预提交挂钩以确保在提交评论中引用了工作项。
    • 我们目前正在这样做,但要以一种保存的方式进行,我们必须使用 Polarion 的 API(在 Java 中提供)来检查工作项是否打开并且可以工作.所以我试图找到一种不使用 Java 来使用该 API 的方法。但是谢谢,这当然是解决方案的一部分。
    • 当您停止为相关项目使用一个存储库时,您也失去了在项目之间移动文件同时保留历史记录、对多个项目执行原子提交、用作轻量级标签的全局修订的可能性。我不会仅仅为了获得更好的钩子性能而推荐此步骤,而是要定义拆分存储库的优点和缺点。
    • @Bert:这些很有趣。我不得不承认,我从来不需要这些功能中的任何一个,但我可以想象有些人会需要,所以你的观点是正确的。就个人而言,我想不出第一点的用例。回复:第 2 点和第 3 点,如果您需要原子提交和全局修订 #,那么我认为,出于所有意图和目的,它们是一个项目,所以应该放在一个 repo 中。
    【解决方案2】:

    基于 Java 的 Hook 脚本速度很慢,通常会影响 Subversion 的响应时间,尤其是。如果您在负载较重的服务器上工作。 将实现最佳绩效以实施审计和指标以提高质量。 通过跟踪审计中的可追溯性,项目团队可以跟踪其进度,获得越来越好的水平。

    【讨论】:

    • 非常感谢您的提示。我们需要预提交挂钩来允许项目拒绝提交通过。所以我们需要一种不使用Java的方法,而是使用Polarion的API。
    【解决方案3】:

    我最近使用 Python 实现了一个 post-commit 钩子,它扫描同一存储库中的不同项目,然后采取相应的行动。我是 Python 新手,因此以下脚本中可能存在一些效率低下(甚至是完全错误),但它确实适用于我们的目的:

    #!/usr/bin/env python
    
    import commands
    from subprocess import *
    import os
    import sys
    
    # This is a post-commit hook.  The arguments passed to the hook
    # are different than a pre-commit hook, and the syntax/use for
    # svnlook will probably be different too.
    
    def check_repo_and_do_stuff(repos, rev):
    
        dirs_changed_cmd =
        p1 = Popen('%s dirs-changed %s -r %s' % (SVNLOOK, repos, rev)
        dirs_changed = p1.communicate[0]
    
        for line in dirs_changed:
    
            if line.find('/part-of-path-for/project1') >= 0:
                do_stuff_for_project1()
    
            if line.find('/part-of-path-for/project2') >= 0:
                do_stuff_for_project2()
    
    def do_stuff_for_project1()...
    
    def do_stuff_for_project2()...
    
    SVNLOOK='/usr/bin/svnlook'
    
    # Take the arguments that svnserve passes on the command-line
    repos = sys.argv[1]
    rev = sys.argv[2]
    
    check_repo_and_do_stuff(repos, rev)
    

    我希望这会有所帮助。

    -扎卡里

    【讨论】:

    • 嗨 Zachary,这让我们了解了如何区分项目(当然也将成为解决方案的一部分)。我发现有一个与 Subversion 的 python 绑定(参见pysvn.tigris.org),可以用来做真正的工作。
    • mliebelt,请注意 pysvn 在使用非本地存储库时非常慢(它会为每个请求打开一个新的远程连接,可能会重做 SSL 协商)。来自上游颠覆的本机 SWIG 绑定,尽管几乎没有记录,但性能要好得多。
    • @CharlesDuffy 感谢您提供有关 SWIG 的信息。我正在将所有subprocess 代码迁移到pysvn 以进行客户端交互。我刚刚查看了 SWIG,如果将来我需要任何服务器端(挂钩)脚本,我会试一试。有没有你推荐的 SVN SWIG 资源?
    【解决方案4】:

    如果 Java 让事情变慢,但 Java 只在一小部分时间内使用,那么我会用轻量级的方式编写挂钩。即在 Windows 上,使用 .bat 文件。然后,对于需要它的项目(或文件或用户),从轻量级挂钩中调用更昂贵的 Java 挂钩。这样,您只会在需要时减慢提交速度。

    【讨论】:

    • 嗨,克里斯,我们找到了相同的解决方案。我们目前运行一个 bash shell 脚本来决定是否必须运行 java 脚本。但是,当它运行时,影响可以在几秒钟内衡量:-)
    • 我没试过,但Nailgun 可能有助于加快基于 Java 的钩子。
    【解决方案5】:

    在许多情况下,繁重的任务最好由监控存储库更改的持续集成服务器来处理。这可确保脚本永远不会减慢存储库的速度,并且这些工具通常可以为构建、验证和更新任务提供更好的错误报告。

    缺点是他们不能否认提交的发生......这些任务必须作为钩子处理,但实际上您可以将大多数工作延迟到一些提交后处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      • 2014-03-22
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多