当我检查特定分支是否已提交时,为什么我的post-commit钩子条件语句不起作用?

时间:2013-10-17 12:27:35

标签: svn cmd visualsvn-server post-commit-hook

我在Windows服务器上通过VisualSVN Server运行Subvbersion,并使用trunk和三个分支设置我的存储库。分支机构是开发,测试和产品。我有一个我想运行的post commit钩子,它在运行提交后更新了一个工作副本,但我只希望它在dev分支中提交时更新该工作副本。

这是我现在的代码......

@setlocal enableextensions enabledelayedexpansion
@echo off
SET str1=%1
IF NOT x%str1:dev=%==x%str1%  (
pushd <path to working copy>
svn update --username <svn_username> --password <svn_password>
echo update complete
)
endlocal

如果我取出条件,则更新在每次提交时运行,因此我知道条件内部的代码。我还测试了条件作为常规批处理文件,发送它像“branches / dev”和“branches / test”这样的字符串,并且在这些测试中表现正常。但是,当我将其保存为我的post-commit钩子脚本时,它永远不会运行,无论提交是在dev分支中还是其他方式。

编辑:根据反馈已经回答了这个问题,我尝试了另一个问题中推荐的方法,但这种方法也没有用。这是我在那里建议的代码版本:

REM The command checks whether the committed revision changes any data under '/dev'
"%VISUALSVN_SERVER%bin\svnlook.exe" dirs-changed %1 --revision %2 | findstr /b "[Dd]ev"

REM If 'findstr' returns error code 0, it means that the commit involves the '/dev' directory.
REM So if the the returned code is 0 the command runs external batch 'post-commit-actions.bat'
If %ERRORLEVEL% EQU 0 call %~dp0post-commit-actions.bat %*

为了使其工作,我在hooks目录中创建了一个名为post-commit-actions.bat的文件来执行svn update。但是,这不是在提交后运行。如果我遗漏任何相关信息,请告诉我。

编辑:谢谢大家的帮助。通过这里的输入,我能够拼凑出一个可行的解决方案。对于那些寻找类似问题答案的人来说,它的工作原理如下:

svnlook dirs-changed %1 -r %2 | findstr /b /i "branches/dev"

IF %ERRORLEVEL% EQU 0 (
    pushd <path-to-working-copy>
    svn update --username <repo-username> --password <repo-password>
)

2 个答案:

答案 0 :(得分:1)

就这样发布,这是解决问题的方法。此代码集的目的是:

svnlook dirs-changed %1 -r %2 | findstr /b /i "branches/dev"

IF %ERRORLEVEL% EQU 0 (
    pushd <path-to-working-copy>
    svn update --username <repo-username> --password <repo-password>
)

感谢您提供此解决方案的所有帮助

答案 1 :(得分:0)

echo不会执行任何操作,因为钩子脚本仅显示STDERR,并且仅在挂钩失败时才显示。 STDOUT永远不会显示。这可能是一个问题吗?

您需要做的是打印出STDERR,故意使您的提交后挂钩失败。不是Windows批处理脚本专家,我没有Windows机器来测试它,但是像这样:

@setlocal enableextensions enabledelayedexpansion
@echo off
SET str1=%1
echo STR1 = %str1% >&2
echo IF NOT x%str1:dev=% == x%str1%x >&2
IF NOT x%str1:dev=%==x%str1%  (
    pushd <path to working copy>
    echo IN directory %CD% >&2
    echo svn update >&2
    svn update --username <svn_username> --password <svn_password>
    echo update complete
)
endlocal
exit 1

echo命令将输出到STDERR,exit 1将强制您的提交后挂钩失败。当您进行提交时,您可以看到正在发生的事情,它可以帮助您确定问题所在。

顺便说一下,不要将Windows批处理脚本用于挂钩。 Windows Batch是......嗯...... 一种古怪的语言。您可以在Windows上使用Perl或Python(甚至是Ruby)。这些方法更强大,更灵活,并且更适合您的钩子脚本。

如果您或您的公司坚持只使用Microsoft解决方案(“Perl和Python是黑客语言。”“我们这里不使用共享软件。”),尝试使用Windows附带的PowerShell。


附录

  

好的,现在它给了我这个:
      Error: STR1 = D:\Repositories\<repository-name>
      Error: IF NOT xD:\Repositories\<repository-name> ==xD:\Repositories\<repository-name>x
  %1不应该有完整的路径,包括branches\dev

现在我们知道问题所在:

我们正在讨论两个不同的事情:

  1. 存储库中有虚拟位置。这是在文件的 URL 中,通常是使用svn(或svnlook命令时)所发生的结果。
  2. 存储库中有物理位置。这是您的存储库在服务器上的实际目录。
  3. 您对文件和目录的虚拟位置感兴趣。 %1实际上是存储库的物理位置 - 驱动器和目录。

    这两个人彼此无关。

    那么,你怎么知道提交是否在dev上?由于单个提交可能位于多个分支上,甚至可能同时存在于主干上,因此您必须完成对该提交所发生的所有更改。通常,您使用svnlook changed命令:

     svnlook changed -r %2 %1
    

    请注意,我使用%1指向存储库的物理位置,而%2是已更改的修订版。

    这会给我一个这样的列表:

    A /dev/foo/
    A /dev/foo/foo.pl
    U /test/bar/bar.pl
    D /trunk/foo/bar/foobar.pl
    

    输出中的第一个字母是添加,删除还是更新了某些内容。第二个是添加,删除或更新的内容。以/结尾的东西是目录而不是文件。

    您必须解析整个输出,并验证dev分支上没有发生任何更改。

    您将如何在标准Windows批处理中执行此操作?我不确定。它可能是可能的,但即使使用更强大的BASH shell,也会有点挑战。这就是为什么我告诉人们使用Python或Perl或一些完整的脚本语言。