2

我正在通过 Windows 服务器上的 VisualSVN 服务器运行 Subvbersion,并且我的存储库设置了一个主干和三个分支。分支是 dev、test 和 prod。我有一个要运行的提交后挂钩,它在运行提交后更新工作副本,但我只希望它在开发分支中进行提交时更新该工作副本。

这是我现在的代码...

@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”之类的字符串,并且在这些测试中表现正常。但是,当我将它保存为我的提交后挂钩脚本时,它永远不会运行,无论提交是在 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 更新。但是,这不是在提交后运行。如果我遗漏了任何相关信息,请告诉我。

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

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>
)
4

2 回答 2

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>
)

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

于 2013-10-21T13:28:46.980 回答
0

The echo isn't going to do anything since hook scripts only display STDERR and only if the hook fails. STDOUT is never displayed. Could that be an issue?

What you need to do is to print out STDERR, and purposefully fail your post-commit hook. Not a Windows batch script expert, and I don't have a Windows machine to test this on, but something like this:

@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

The echo commands will output to STDERR and the exit 1 will force your post-commit hook to fail. When you do a commit, you can see what's going on, and it may help you determine where your problem lies.

By the way, Don't use Windows batch scripts for hooks. Windows Batch is ...um... a quirky language. You can use either Perl or Python ( or even Ruby ) on Windows. These are way more powerful, flexible, and will work better for your hook scripts.

If you or your company insist on Microsoft only solutions ("Perl and Python are hacker languages." or "We don't use shareware here.") , try using PowerShell which comes with Windows.


Addendum

Ok, now it's giving me this:
Error: STR1 = D:\Repositories\<repository-name>
Error: IF NOT xD:\Repositories\<repository-name> ==xD:\Repositories\<repository-name>x
Shouldn't %1 have the whole path, including branches\dev?

Now we know what the issue is:

There are two different things we're talking about:

  1. There's the virtual location in the repository. This is in the URL of the file and usually the result of what happens when you use the svn (or svnlook command).
  2. there's the physical location in the repository. This is the actual directory where your repository sits on your server.

You are interested in the virtual location of the files and directories. What %1 actually is is the physical location of the repository -- what drive and directory.

The two have nothing to do with each other.

So, how can you tell if a commit was on dev? Since it is possible for a single commit to be on multiple branches, and even on trunk at the same time, you would have to go through all the changes that took place on that commit. Usually, you use the svnlook changed command:

 svnlook changed -r %2 %1

Note that I use the %1 to point to the physical location of the repository while %2 is the revision that was changed.

This will give me a listing like this:

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

The first letter in the output is whether something was added, deleted, or updated. The second is what was added, deleted, or updated. Something that ends with a / is a directory and not a file.

You would have to parse the entire output, and verify that none of the changes took place on the dev branch.

How would you do this in standard Windows Batch? I'm not sure. It might be possible, but even with BASH shell, which is way more powerful, it would be a bit of a challenge. This is why I tell people to use Python or Perl or some full level scripting language.

于 2013-10-17T15:23:28.947 回答