[svn] What is a pre-revprop-change hook in SVN, and how do I create it?

I wanted to edit a log comment in the repository browser and received an error message that no pre-revprop-change hook exists for the repository. Besides having a scary name, what is a pre-revprop-change hook, and how do I create it?

This question is related to svn svn-hooks

The answer is


For Windows, here's a link to an example batch file that only allows changes to the log message (not other properties):

http://ayria.livejournal.com/33438.html

Basically copy the code below into a text file and name it pre-revprop-change.bat and save it in the \hooks subdirectory for your repository.

@ECHO OFF
:: Set all parameters. Even though most are not used, in case you want to add
:: changes that allow, for example, editing of the author or addition of log messages.
set repository=%1
set revision=%2
set userName=%3
set propertyName=%4
set action=%5

:: Only allow the log message to be changed, but not author, etc.
if /I not "%propertyName%" == "svn:log" goto ERROR_PROPNAME

:: Only allow modification of a log message, not addition or deletion.
if /I not "%action%" == "M" goto ERROR_ACTION

:: Make sure that the new svn:log message is not empty.
set bIsEmpty=true
for /f "tokens=*" %%g in ('find /V ""') do (
set bIsEmpty=false
)
if "%bIsEmpty%" == "true" goto ERROR_EMPTY

goto :eof

:ERROR_EMPTY
echo Empty svn:log messages are not allowed. >&2
goto ERROR_EXIT

:ERROR_PROPNAME
echo Only changes to svn:log messages are allowed. >&2
goto ERROR_EXIT

:ERROR_ACTION
echo Only modifications to svn:log revision properties are allowed. >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

For PC users: The .bat extension did not work for me when used on Windows Server maching. I used VisualSvn as Django Reinhardt suggested, and it created a hook with a .cmd extension.


Thanks #patmortech

And I added your code which "only the same user can change his code".

:: Only allow editing of the same user.
for /f "tokens=*" %%a in ( 
'"%VISUALSVN_SERVER%\bin\svnlook.exe" author -r %revision% %repository%') do ( 
set orgAuthor=%%a
)
if /I not "%userName%" == "%orgAuthor%" goto ERROR_SAME_USER

If you want to save the changes on the log messages, use the batch script from the answer above from @patmortech (https://stackoverflow.com/a/468475),
who copied the script from https://stackoverflow.com/a/68850,
and add these lines between if "%bIsEmpty%" == "true" goto ERROR_EMPTY and goto :eofbefore:

set outputFile=%repos%\log-change-history.txt

echo User '%user%' changes log message in rev %rev% on %date% %time%.>>%outputFile%
echo ----- Old message: ----->>%outputFile%
svnlook propget --revprop %repos% svn:log -r %rev% >>%outputFile%
echo.>>%outputFile%
echo ----- New message: ----->>%outputFile%
for /f "tokens=*" %%g in ('find /V ""') do (echo %%g >>%outputFile%)
echo ---------->>%outputFile%
echo.>>%outputFile%

It will create a text file log-change-history.txt in the repo folder on the server and append each log change notification.


For Windows, here's a link to an example batch file that only allows changes to the log message (not other properties):

http://ayria.livejournal.com/33438.html

Basically copy the code below into a text file and name it pre-revprop-change.bat and save it in the \hooks subdirectory for your repository.

@ECHO OFF
:: Set all parameters. Even though most are not used, in case you want to add
:: changes that allow, for example, editing of the author or addition of log messages.
set repository=%1
set revision=%2
set userName=%3
set propertyName=%4
set action=%5

:: Only allow the log message to be changed, but not author, etc.
if /I not "%propertyName%" == "svn:log" goto ERROR_PROPNAME

:: Only allow modification of a log message, not addition or deletion.
if /I not "%action%" == "M" goto ERROR_ACTION

:: Make sure that the new svn:log message is not empty.
set bIsEmpty=true
for /f "tokens=*" %%g in ('find /V ""') do (
set bIsEmpty=false
)
if "%bIsEmpty%" == "true" goto ERROR_EMPTY

goto :eof

:ERROR_EMPTY
echo Empty svn:log messages are not allowed. >&2
goto ERROR_EXIT

:ERROR_PROPNAME
echo Only changes to svn:log messages are allowed. >&2
goto ERROR_EXIT

:ERROR_ACTION
echo Only modifications to svn:log revision properties are allowed. >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

If you want to save the changes on the log messages, use the batch script from the answer above from @patmortech (https://stackoverflow.com/a/468475),
who copied the script from https://stackoverflow.com/a/68850,
and add these lines between if "%bIsEmpty%" == "true" goto ERROR_EMPTY and goto :eofbefore:

set outputFile=%repos%\log-change-history.txt

echo User '%user%' changes log message in rev %rev% on %date% %time%.>>%outputFile%
echo ----- Old message: ----->>%outputFile%
svnlook propget --revprop %repos% svn:log -r %rev% >>%outputFile%
echo.>>%outputFile%
echo ----- New message: ----->>%outputFile%
for /f "tokens=*" %%g in ('find /V ""') do (echo %%g >>%outputFile%)
echo ---------->>%outputFile%
echo.>>%outputFile%

It will create a text file log-change-history.txt in the repo folder on the server and append each log change notification.


The name of the hook script is not so scary if you manage decipher it: it's pre revision property change hook. In short, the purpose of pre-revprop-change hook script is to control changes of unversioned (revision) properties and to send notifications (e.g. to send an email when revision property is changed).

There are 2 types of properties in Subversion:

  • versioned properties (e.g svn:needs-lock and svn:mime-type) that can be set on files and directories,
  • unversioned (revision) properties (e.g. svn:log and svn:date) that are set on repository revisions.

Versioned properties have history and can be manipulated by ordinary users who have Read / Write access to a repository. On the other hand, unversioned properties do not have any history and serve mostly maintenance purpose. For example, if you commit a revision it immediately gets svn:date with UTC time of your commit, svn:author with your username and svn:log with your commit log message (if you specified any).

As I already specified, the purpose of pre-revprop-change hook script is to control changes of revision properties. You don't want everyone who has access to a repository to be able to modify all revision properties, so changing revision properties is forbidden by default. To allow users to change properties, you have to create pre-revprop-change hook.

The simplest hook can contain just one line: exit 0. It will allow any authenticated user to change any revision property and it should not be used in real environment. On Windows, you can use batch script or PowerShell-based script to implement some logic within pre-revprop-change hook.

This PowerShell script allows to change svn:log property only and denies empty log messages.

# Store hook arguments into variables with mnemonic names
$repos    = $args[0]
$rev      = $args[1]
$user     = $args[2]
$propname = $args[3]
$action   = $args[4]

# Only allow changes to svn:log. The author, date and other revision
# properties cannot be changed
if ($propname -ne "svn:log")
{
  [Console]::Error.WriteLine("Only changes to 'svn:log' revision properties are allowed.")
  exit 1
}

# Only allow modifications to svn:log (no addition/overwrite or deletion)
if ($action -ne "M")
{
  [Console]::Error.WriteLine("Only modifications to 'svn:log' revision properties are allowed.")
  exit 2
}

# Read from the standard input while the first non-white-space characters
$datalines = ($input | where {$_.trim() -ne ""})
if ($datalines.length -lt 25)
{
  # Log message is empty. Show the error.
  [Console]::Error.WriteLine("Empty 'svn:log' properties are not allowed.")
  exit 3
}

exit 0

This batch script allows only "svnmgr" user to change revision properties:

IF "%3" == "svnmgr" (goto :label1) else (echo "Only the svnmgr user may change revision properties" >&2 )

exit 1
goto :eof

:label1
exit 0

Thanks #patmortech

And I added your code which "only the same user can change his code".

:: Only allow editing of the same user.
for /f "tokens=*" %%a in ( 
'"%VISUALSVN_SERVER%\bin\svnlook.exe" author -r %revision% %repository%') do ( 
set orgAuthor=%%a
)
if /I not "%userName%" == "%orgAuthor%" goto ERROR_SAME_USER

For Linux to allow the edition of a log comment,

  • locate the file pre-revprop-change.tmpl in the hooks directory of your repository
  • copy the file to the same directory, renaming it to pre-revprop-change
  • give execute permission to the file (for the server user, e.g. www-data)

Edited: (thanks to lindes)

  • after that you might have to edit the script to return an exit value of 0 for the kind of edits, that you want to allow.

For Windows, here's a link to an example batch file that only allows changes to the log message (not other properties):

http://ayria.livejournal.com/33438.html

Basically copy the code below into a text file and name it pre-revprop-change.bat and save it in the \hooks subdirectory for your repository.

@ECHO OFF
:: Set all parameters. Even though most are not used, in case you want to add
:: changes that allow, for example, editing of the author or addition of log messages.
set repository=%1
set revision=%2
set userName=%3
set propertyName=%4
set action=%5

:: Only allow the log message to be changed, but not author, etc.
if /I not "%propertyName%" == "svn:log" goto ERROR_PROPNAME

:: Only allow modification of a log message, not addition or deletion.
if /I not "%action%" == "M" goto ERROR_ACTION

:: Make sure that the new svn:log message is not empty.
set bIsEmpty=true
for /f "tokens=*" %%g in ('find /V ""') do (
set bIsEmpty=false
)
if "%bIsEmpty%" == "true" goto ERROR_EMPTY

goto :eof

:ERROR_EMPTY
echo Empty svn:log messages are not allowed. >&2
goto ERROR_EXIT

:ERROR_PROPNAME
echo Only changes to svn:log messages are allowed. >&2
goto ERROR_EXIT

:ERROR_ACTION
echo Only modifications to svn:log revision properties are allowed. >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

  1. Go to SVN repo directory into the subfolder "hooks", e.g. "D:\SVN\hooks\"
  2. create the empty file "pre-revprop-change.bat" there
  3. in the file write "exit 0" (without "") and save it
  4. enjoy :)

(This solution surely has drawbacks, as nothing is checked/prohibited. But for my case - a local repo that only I am using - it seems to work.)


The name of the hook script is not so scary if you manage decipher it: it's pre revision property change hook. In short, the purpose of pre-revprop-change hook script is to control changes of unversioned (revision) properties and to send notifications (e.g. to send an email when revision property is changed).

There are 2 types of properties in Subversion:

  • versioned properties (e.g svn:needs-lock and svn:mime-type) that can be set on files and directories,
  • unversioned (revision) properties (e.g. svn:log and svn:date) that are set on repository revisions.

Versioned properties have history and can be manipulated by ordinary users who have Read / Write access to a repository. On the other hand, unversioned properties do not have any history and serve mostly maintenance purpose. For example, if you commit a revision it immediately gets svn:date with UTC time of your commit, svn:author with your username and svn:log with your commit log message (if you specified any).

As I already specified, the purpose of pre-revprop-change hook script is to control changes of revision properties. You don't want everyone who has access to a repository to be able to modify all revision properties, so changing revision properties is forbidden by default. To allow users to change properties, you have to create pre-revprop-change hook.

The simplest hook can contain just one line: exit 0. It will allow any authenticated user to change any revision property and it should not be used in real environment. On Windows, you can use batch script or PowerShell-based script to implement some logic within pre-revprop-change hook.

This PowerShell script allows to change svn:log property only and denies empty log messages.

# Store hook arguments into variables with mnemonic names
$repos    = $args[0]
$rev      = $args[1]
$user     = $args[2]
$propname = $args[3]
$action   = $args[4]

# Only allow changes to svn:log. The author, date and other revision
# properties cannot be changed
if ($propname -ne "svn:log")
{
  [Console]::Error.WriteLine("Only changes to 'svn:log' revision properties are allowed.")
  exit 1
}

# Only allow modifications to svn:log (no addition/overwrite or deletion)
if ($action -ne "M")
{
  [Console]::Error.WriteLine("Only modifications to 'svn:log' revision properties are allowed.")
  exit 2
}

# Read from the standard input while the first non-white-space characters
$datalines = ($input | where {$_.trim() -ne ""})
if ($datalines.length -lt 25)
{
  # Log message is empty. Show the error.
  [Console]::Error.WriteLine("Empty 'svn:log' properties are not allowed.")
  exit 3
}

exit 0

This batch script allows only "svnmgr" user to change revision properties:

IF "%3" == "svnmgr" (goto :label1) else (echo "Only the svnmgr user may change revision properties" >&2 )

exit 1
goto :eof

:label1
exit 0

Here is the link to the stack overflow question with many common hooks Common Types of Subversion Hooks, including the original source of the pre-revprop-change hook for Windows cross-posted here.

You should refer there as they may get improved over time.


  1. Go to SVN repo directory into the subfolder "hooks", e.g. "D:\SVN\hooks\"
  2. create the empty file "pre-revprop-change.bat" there
  3. in the file write "exit 0" (without "") and save it
  4. enjoy :)

(This solution surely has drawbacks, as nothing is checked/prohibited. But for my case - a local repo that only I am using - it seems to work.)


For PC users: The .bat extension did not work for me when used on Windows Server maching. I used VisualSvn as Django Reinhardt suggested, and it created a hook with a .cmd extension.


For Linux to allow the edition of a log comment,

  • locate the file pre-revprop-change.tmpl in the hooks directory of your repository
  • copy the file to the same directory, renaming it to pre-revprop-change
  • give execute permission to the file (for the server user, e.g. www-data)

Edited: (thanks to lindes)

  • after that you might have to edit the script to return an exit value of 0 for the kind of edits, that you want to allow.

This was the easiest for me on a Windows Server: In VisualSVN right-click your repository, then select Properties... and then the Hooks tab.

Select Pre-revision property change hook, click Edit.

I needed to be able to change the Author - it often happens on remote computers used by multiple people, that by mistake we check-in using someone else's stored credentials.

Here is the modified community wiki script to paste:

@ECHO OFF
:: Set all parameters. Even though most are not used, in case you want to add
:: changes that allow, for example, editing of the author or addition of log messages.
set repository=%1
set revision=%2
set userName=%3
set propertyName=%4
set action=%5

:: Only allow the author to be changed, but not message ("svn:log"), etc.
if /I not "%propertyName%" == "svn:author" goto ERROR_PROPNAME

:: Only allow modification of a log message, not addition or deletion.
if /I not "%action%" == "M" goto ERROR_ACTION

:: Make sure that the new svn:log message is not empty.
set bIsEmpty=true
for /f "tokens=*" %%g in ('find /V ""') do (
set bIsEmpty=false
)
if "%bIsEmpty%" == "true" goto ERROR_EMPTY

goto :eof

:ERROR_EMPTY
echo Empty svn:author messages are not allowed. >&2
goto ERROR_EXIT

:ERROR_PROPNAME
echo Only changes to svn:author messages are allowed. >&2
goto ERROR_EXIT

:ERROR_ACTION
echo Only modifications to svn:author revision properties are allowed. >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

This was the easiest for me on a Windows Server: In VisualSVN right-click your repository, then select Properties... and then the Hooks tab.

Select Pre-revision property change hook, click Edit.

I needed to be able to change the Author - it often happens on remote computers used by multiple people, that by mistake we check-in using someone else's stored credentials.

Here is the modified community wiki script to paste:

@ECHO OFF
:: Set all parameters. Even though most are not used, in case you want to add
:: changes that allow, for example, editing of the author or addition of log messages.
set repository=%1
set revision=%2
set userName=%3
set propertyName=%4
set action=%5

:: Only allow the author to be changed, but not message ("svn:log"), etc.
if /I not "%propertyName%" == "svn:author" goto ERROR_PROPNAME

:: Only allow modification of a log message, not addition or deletion.
if /I not "%action%" == "M" goto ERROR_ACTION

:: Make sure that the new svn:log message is not empty.
set bIsEmpty=true
for /f "tokens=*" %%g in ('find /V ""') do (
set bIsEmpty=false
)
if "%bIsEmpty%" == "true" goto ERROR_EMPTY

goto :eof

:ERROR_EMPTY
echo Empty svn:author messages are not allowed. >&2
goto ERROR_EXIT

:ERROR_PROPNAME
echo Only changes to svn:author messages are allowed. >&2
goto ERROR_EXIT

:ERROR_ACTION
echo Only modifications to svn:author revision properties are allowed. >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

Here is the link to the stack overflow question with many common hooks Common Types of Subversion Hooks, including the original source of the pre-revprop-change hook for Windows cross-posted here.

You should refer there as they may get improved over time.