Could you please guide me on how svnlook
is working below. I want to include this in a hook to prevent commits in a tag under /tags
:
$SVNLOOK changed -t "$TXN" "$REPOS" | grep "^U\W.*\/tags\/" && /bin/echo "Cannot commit to tags!" 1>&2 && exit 1
A Subversion pre-commit hook will allow a commit to go through if it returns an exit code of
0
. Otherwise, the pre-commit hook will fail and the commit will not be processed.The
$SVNLOOK changed -t "$TXN" "$REPOS"
will show the changes in$REPOS
that took place in$TXN
. The shell variables must be set by you. If you look at thepre-commit
script that comes with Subversion, you'll see:The output of the
svnlook changed
command looks like this:The first column is whether something was Uprated, Added, or Deleted. The second column refers to attributes.
The rest is the name of the file that was acted upon. You can see that
baguette.txt
was deleted, and that a property oncroissant.txt
was changed, but the file itself wasn't updated.Let's say someone tried to change a tag. The output of
svnlook changed
will look like this:The grep command is this:
This is looking for a line that starts with
^U
meaning it was an update. Then, it looks for a string that begins with/tags
. Hmmm... that might be an issue. It doesn't match the output of thesvnlook changed
command.Maybe it should be:
This will match any string that starts with
U
, possibly followed by another character, followed by whitespace, and then immediately the wordtags/
.You might want to verify that expression.
The
&&
is a list operator. If the expression on the left side of&&
executes successfully (i.e. it returns a zero exit code), the statement on the right side will be executed. Otherwise, the statement on the right won't be executed.Thus, if your
grep
matches a pattern that looks like someone updated a tag, it will be true. The statement on the right side of the&&
will be executed.Thus,
will be executed. This is sent to STDERR which will be sent to the Subversion client, but only if the exit code of the pre-commit hook is zero.
Thus the next list operator command
exit 1
will execute if the/bin/echo
is successful. (It might not be, but usually will be). With that, the pre-commit hook exits with a non-zero exit code, the hook fails, and theCannot commit to tags!
will be sent to the SVN client for the user to see.There is absolutely no reason in the world for this statement to look like this. This is almost equivalent, and is easier to understand:
After all, you need to put this in a shell script called
pre-commit
anyway and have the shell variables$SVNLOOK
,$REPOS
, and$TXN
set anyway.The reason this isn't quite equivalent is that this will fail the commit even if the
/bin/echo
fails.If you are looking for a pre-commit hook to control tags, you should take a look at mine. This has been tested on hundreds of site, and will give you a lot more control over your repository and does better error checking.
This hook uses a control file to control access to the repository. For example, you might want to be able to let yourself change tags if necessary.
Take a look at the hook. It works with the standard Perl 5.8.8 installation and up. It requires no other modules. However, if you use LDAP or Active Directory for Subversion access control, you can install the
Net::LDAP
Perl module and use LDAP or Active Directory groups in your pre-commit hook for access control.