[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Tutorial: hook scripts and conf files under version control

From: Brandt, Servatius <Servatius.Brandt_at_fujitsu-siemens.com>
Date: 2005-06-03 12:10:38 CEST


I've written a tutorial how to put Subversion hook scripts and
configuration files under version control. This seems to be an issue
many people are interested in. So if there is a place where it will be
found easily, feel free to put it there. If you are able to improve it,
go ahead. All rights reserved for everyone who wants to make the life
of other people easier. Discussions welcome.

- Servatius

 How to put configuration files and hook scripts under version control

                               A tutorial

                      written by Servatius Brandt

Create a fresh repository and add a project named "repos" where to put
the repository files in the conf and hooks directories under version
control. Check out this (empty) project to the repository top

    $ svnadmin create repos
    $ cd repos
    $ svn mkdir file://$PWD/repos -m 'Project "repos" to keep the '\
    'repository files themselves under version control'
    $ svn checkout file://$PWD/repos .

Set the svn:ignore property on the repository top directory to ignore
the directories and files not put under version control.

    $ svn propset svn:ignore 'format
    locks' .
    $ svn commit -m 'Ignore property on repos project for repository '\
    'files not under version control'

Add the files and directories to be put under version control:
svn import doesn't care about the svn:ignore property, so don't do it
this way:
    $ svn import . file://$PWD/repos
Better add the files explicitly:

    $ svn status # add files reported by this command:
    $ svn add README.txt conf hooks
    $ svn commit -m 'Repository files put under version control: '\
    'README.txt, conf/, hooks/'

Create an extra repository for playing around on unimportant stuff.
Make it a working copy of the files put under version control in the
real repository. This means that you share the conf and hooks
directories with the real repository but can try out any changes on
the toy repository first.

    $ svnadmin create ../repos-play
    $ cd ../repos-play
    $ rm -rf README.txt conf hooks
    $ svn checkout file://$OLDPWD/repos . # use real repository files

Imagine you have made some well-tested changes in the configuration
files or hook scripts of the toy repository and commit them. This will
store your changes to the repos project of the real repository.
However, to cause it to actually use these files, you need to update its
working copy to get the new files from the repos project. You can
automate this by adding a post-commit hook which executes an svn update
for the repos project. Of course, you make these changes in the toy
repository to test them before the commit. It's easiest to start with
a copy of the post-commit hook template.

    $ cd hooks
    $ svn copy post-commit.tmpl post-commit
    $ svn propset svn:executable '' post-commit
    $ vim post-commit

Comment out the predefined code from the template. (You can add it in
a later step after setting up the automatic update.) Change the leading
#!/bin/sh to #!/bin/ksh or #!/bin/bash and paste the following code into
the file:

    # The configuration files and hook scripts of this repository
    # have been put under version control in the repository itself.
    # The files actually used are working copies from its "repos"
    # project. When committing changes for these files, update them
    # automatically. This allows to check out the files to a different
    # toy repository and to change and test them there, and when all
    # works fine, the final commit causes the changes to be updated to
    # the real repository.
    if [[ $REPOS != *-play ]] && \
        $(svnlook dirs-changed $REPOS | grep '^repos/' >/dev/null)
        umask 022 # don't allow others to change the repository files
        svn update $REPOS

Use an umask that denies file permissions you don't want when the
automatic update is made. Commit your changes to the repos project of
the real repository. Since the post-commit hook is not yet present in
the hooks directory of the real repository's working copy, you need to
update it yourself this first time.

    $ svn commit post-commit -m 'Automatic update of conf/ and hooks/ '\
    'files when commited from a test repository'
    $ cd ../../repos
    $ svn update

Now you can set up the rest of the configuration for your repository.
Always make all changes in the toy repository and commit them after
testing. They real repository is updated then automatically.

Let's start with setting up the permissions for the repository:

    $ cd ../repos-play/conf
    $ vim svnserve.conf # edit as you like
    $ vim passwd # edit as you like
    $ svn commit

The commit has updated the conf/svnserve.conf and conf/passwd files
in the real repository. You can check this by using the svn status

    $ svn status -v
    $ cd ../../repos
    $ svn status -v # lists last commit's rev numbers for all files

Using the same permissions and configuration for the real and the toy
repository is a good idea: So any member of your project group who is
new to Subversion can make his first experience on the toy repository.
And even later on, he can use it for trying out things he has not yet
used (e.g. branches). And you yourself can use the toy repository for
testing any changes to the conf and hooks files without disturbing the
work of the group on the real repository.

Note: Adding the README.txt file to the repos project makes sense
because it contains a warning not to modify files in case someone
accidentally checks out this project. Of course, you can restrict the
access in the pre-commit hook script. You can also add a remark about
using a toy repository for changes and about the automatic update on

Now you can set up the rest of the configuration and hook scripts for
the real repository. (Always test the changes in the toy repository and
commit from there.) You may want to check for a repository name ending
in "-play" to avoid commit mails for changes on the toy repository etc.
Then you can add the initial project structure tree to the real

Be beware of a security risk: only the repository administrators (maybe
just you) should have the permissions to commit changes to the "repos"
project. This prevents other users from changing the configuration
files that define the access rights. You can use a script like
svnperms.py to do this.

If you want to put repository files of an existing repository under
version control, just leave out the svn create at the very beginning and
add your existing configuration files and hook scripts to the "repos"
project of your existing repository.

                  Additional hints for Windows/Cygwin:

If you did all this on a Windows system under Cygwin, you might want
to work on the same working copies with several different Subversion
clients, e.g. the cygwin client, the native Windows client, and a GUI
client like TortoiseSVN. But there is a problem since Cygwin uses POSIX
paths. If your repository is on D:\repos, svn info shows:

    $ svn info # output: URL: file:///cygdrive/d/repos/repos

Note that the second "repos" is the project name to which you put the
files below /cygdrive/d/repos under version control. The native Windows
command-line client and the GUI clients don't understand such POSIX path
URLs. You can solve this problem by relocating them to a file system
independent form by using svnserve. Do this for the toy repository so
that you can commit changes to the real repository from any client.

    $ cd ../repos-play
    $ svn switch --relocate file:///cygdrive/d svn:///
    $ svnserve -d -r /cygdrive/d

    $ svn info # output: URL: svn:///repos/repos

svn:/// means accessing the repository in D:\ on the local machine,
which is the same as using svn://localhost/. Ensure that you have set
up write permissions for yourself in D:\repos\conf\svnserve.conf and
D:\repos\conf\passwd, so that you can commit changes to the repository.
Unlike file:///, the default access for svn:/// is read-only (for
everyone) since svnserve provides access to the network. Even on
a local system not attached to a network, you should use password
protection to avoid that your changes are committed anonymously:
svnserve does not know that's just you who commit, you have to tell it
by a user = password entry (see conf/svnserve.conf, conf/passwd above).

It is important to use the Cygwin version of svnserve, not the native
Windows version. This avoids to worry about creating .bat versions of
your hook scripts. Just write them as (arbitrary) shell scripts (using
the #! syntax) and set the svn:executable property. Even if you use
a Windows client for committing, the Cygwin svnserve will execute the
hook scripts perfectly.

It is also advisable, to use an fsfs-type repository to avoid
compatibility problems with different versions of the Berkeley
database used by the native and the Cygwin svnserve.

On Windows, there is one exception where the automatic update in the
real repository doesn't work when committing changes to the repository
files tested in the toy repository: when you commit a change to the
post-commit hook script itself. Windows doesn't permit an update on
this file as long as it is executed by the shell. If you try, you'll
get a post-commit.tmp file in the hook directory of the real repository.
In this case you have to update in-place.

Servatius Brandt Phone: +49 89 636-41504
Fujitsu Siemens Computers Fax: +49 89 636-48716
EP SW AD C++ Email: Servatius.Brandt@fujitsu-siemens.com

To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Fri Jun 3 12:13:51 2005

This is an archived mail posted to the Subversion Users mailing list.