I'm running Subvbersion through VisualSVN Server on a Windows server and have my repository set up with a trunk and three branches. The branches are dev, test and prod. I have a post commit hook that I want to run which updates a working copy after a commit is run, but I only want it to update that working copy if the commit was made in the dev branch.
This is the code I have right now...
@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
If I take out the conditional, the update runs on every commit, so I know the code inside the conditional works. I have also tested the conditional as a regular batch file, sending it strings like "branches/dev" and "branches/test" and it behaved properly in those tests. However, when I save this as my post-commit hook script, it never runs, whether the commit is in the dev branch or otherwise.
EDIT: Based on feedback that this question was already answered, I tried the approach recommended in the other question, but that approach is not working either. Here is my version of the code suggested there:
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 %*
In order for this to work, I have created a file in the hooks directory called post-commit-actions.bat to execute the svn update. However, this is not running post-commit. If I'm leaving out any pertinent information, please let me know.
EDIT: Thanks for everyone's help. With the input here, I was able to piece together a working solution. For those looking for an answer to a similar problem, it worked like this:
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>
)
Just so it's posted, here was the solution to the problem. This code-set worked for the purpose intended:
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>
)
Thanks for all of the help in deriving this solution
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, includingbranches\dev
?
Now we know what the issue is:
There are two different things we're talking about:
- 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
(orsvnlook
command). - 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.
来源:https://stackoverflow.com/questions/19426757/why-is-my-post-commit-hook-conditional-statement-not-working-when-i-check-to-see