Inscrutable Design

Ongoing adventures in agile development.

Getting Started With Subversion

Tuesday, July 8, 2008 | Posted in Tools

If a good chair is A Developer's Second Most Important Asset, then revision control is probably next on the list. A good version control system enables collaboration and centralizes backups, but it's also a safety net. Any change can be undone and any file restored. Refactor, delete unused code, try out new ideas - the way it was (when it worked) is only a click away. Lowering the cost of change is a good thing.

I'm going to walk through the Subversion configuration I'm using for my repository. We'll install the application, create a repository, and add user accounts. As an added bonus, we'll configure the repository layout from the command line to veryify that everything's working correctly. For those of you familiar with CVS, there are a few key differences to be aware of:

  • Repository setup isn't quite as automatic as it is in CVS. You'll need to create directories for the trunk, branches, and tags.
  • You can move files within the repository without losing their revision history.
  • Subversion uses repository-wide revision numbers - it's like automatically tagging every commit.

Step 1: Install Subversion.

If you're running Debian or Ubuntu, you can install Subversion using apt. Otherwise, check the subversion binary packages page for installation instructions for your distribution. We'll also need to create an account to run the svnserve daemon and a base directory to hold our repositories. You can put them anywhere you like, but for the purposes of this example I'm going to use /var/svnroot.

sudo apt-get install subversion
sudo groupadd svn
sudo adduser -s /bin/false -g svn svn
sudo mkdir /var/svnroot
sudo chown -R svn:svn /var/svnroot

Now you're ready to start the server. See the svnserve man page for details. Pay special attention to the -r option. This tells svnserve where to look for subversion repositories. It doesn't actually create a repository - we'll handle that in the next step.

sudo -u svn svnserve -d -r /var/svnroot/

Don't forget to open a hole in your firewall. The svnserve daemon uses TCP port 3690 by default, but you can specify a different value using --listen-port=port. If everything's configured correctly, you should be able to connect via telnet.

etch:~ crh$ telnet localhost 3690
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline svndiff1 absent-entries ) ) )

Feel free to use this startup script as a base:

#!/bin/sh

case "$1" in
	start)
		echo "Starting svnserve..."
		sudo -u svn svnserve -d --listen-host=svn.inscrutabledesign.com -r /var/svnroot/
	;;
	stop)
		echo "Stopping svnserve..."
		killall svnserve
	;;
	*)
		echo "Usage: $0 [start|stop]"
	;;
esac

Step 2: Create a repository.

Now that svnserve is up and running, it's time to create a repository. There are two key points to remember. First, the repositories must be under the root set (with the -r option) when svnserve was started. Second, they should be owned by the same user the daemon is running as.

sudo svnadmin create /var/svnroot/examples
sudo chown -R svn:svn /var/svnroot/examples

Your repository, /var/svnroot/examples, should look like this:

-rw-r--r-- 1 svn svn  229 Jul  8 22:31 README.txt
drwxr-xr-x 2 svn svn 4096 Jul  8 22:31 conf
drwxr-xr-x 2 svn svn 4096 Jul  8 22:31 dav
drwxr-sr-x 5 svn svn 4096 Jul  8 22:31 db
-r--r--r-- 1 svn svn    2 Jul  8 22:31 format
drwxr-xr-x 2 svn svn 4096 Jul  8 22:31 hooks
drwxr-xr-x 2 svn svn 4096 Jul  8 22:31 locks

Let's take a look at the conf directory:

-rw-r--r-- 1 svn svn  684 Jul  8 22:31 authz
-rw-r--r-- 1 svn svn  309 Jul  8 22:31 passwd
-rw-r--r-- 1 svn svn 1457 Jul  8 22:31 svnserve.conf

Access control options are defined in svnserve.conf. There are two different user types, ananymous and authenticated, and their permissions can be configured using the anon-access and auth-access options. Each user type can be set to "read", "write", or "none". If you'd like to deny access to anonymous users, just set "anon-access" to "none". To configure user accounts, you'll also need to uncomment the "password-db" option. Your configuration file should look similar to this:

### This file controls the configuration of the svnserve daemon, if you
### use it to allow access to this repository.  (If you only allow
### access through http: and/or file: URLs, then this file is
### irrelevant.)

### Visit http://subversion.tigris.org/ for more information.

[general]
### These options control access to the repository for unauthenticated
### and authenticated users.  Valid values are "write", "read",
### and "none".  The sample settings below are the defaults.
anon-access = read
auth-access = write
### The password-db option controls the location of the password
### database file.  Unless you specify a path starting with a /,
### the file's location is relative to the conf directory.
### Uncomment the line below to use the default password file.
password-db = passwd
### The authz-db option controls the location of the authorization
### rules for path-based access control.  Unless you specify a path
### starting with a /, the file's location is relative to the conf
### directory.  If you don't specify an authz-db, no path-based access
### control is done.
### Uncomment the line below to use the default authorization file.
# authz-db = authz
### This option specifies the authentication realm of the repository.
### If two repositories have the same authentication realm, they should
### have the same password database, and vice versa.  The default realm
### is repository's uuid.
# realm = My First Repository

Once "password-db" is uncommented, creating user accounts is as simple as adding a username and password to the passwd file. If you want a little more control over what users can access, check out the authz file. You'll need to uncomment the "authz-db" line in svnserve.conf to use it. Those passwords are stored in plain text - it would probably be wise to ensure that the whole repository structure is only readable by svn user.

sudo chmod -R 700 /var/svnroot

Step 3: Create directories for the trunk, branches, and tags.

Collabnet has an excellent article on Subversion repository layout. Take a quick read through that before continuing. Once you've decided on a layout:

# Check out your repository.
cd /tmp
svn co svn://localhost/examples
cd examples

# Create a directory structure using svn.
svn mkdir trunk
svn mkdir trunk/example_module_1
svn mkdir trunk/example_module_2
svn mkdir branches
svn mkdir tags

# A layout like this is also an option.
#svn mkdir example_module_1
#svn mkdir example_module_1/trunk
#svn mkdir example_module_1/branches
#svn mkdir example_module_1/tags
#svn mkdir example_module_2
#svn mkdir example_module_2/trunk
#svn mkdir example_module_2/branches
#svn mkdir example_module_2/tags

# Then commit your changes with a comment.  You should be prompted
# for a username and password if they're required for write access.
svn ci -m "Created base directories."

Once your directory structure is in place you can check out the latest version of your code using:

svn co http://myserver.com/examples/trunk

That's it, you're up and running with a basic repository! There are a lot of different options available - check out the Subversion book for all the details.

Chris Hall