I work with a few clients who do not own a source code repository. I try to educate them about the benefits of putting their project under a Version Control System but it takes time to convince them.

As the developer of their application, I feel the need for such a service. I want to track the changes made to the source code, tag a version when I deliver a release or be able to figure out what precisely changed between 2 releases.

That’s why I had to find my own solution. Since I know Subversion, I came up with a Subversion repository installed on my Macbook. Actually it’s pretty simple and here are the steps to do that.

Firstly, install the whole Subversion package on your Mac. There used to be many variants available, depending on the version of OS X you use. Now it looks like CollabNet glue them all into one Universal binary object, which is a great initiative.

Once installed, use a terminal (iTerm is cool) to create your own SVN repository. I put it under my home directory since it’s for a personal use.

$ mkdir -p ~/repositories/svn
$ svnadmin create ~/repositories/svn/local

Since I want a simple setup, I use the svnserve server available with the Subversion package. Edit svnserve.conf to configure how authentication and authorization works. I just change the general section to disallow anonymous access, grant all permissions to any authenticated users and ask svnserve to look into the passwd file for valid credentials.

$ vi ~/repositories/svn/local/conf/svnserve.conf

[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 = none
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 directory containing
### this configuration file.
### If SASL is enabled (see below), this file will NOT be used.
### Uncomment the line below to use the default password file.
password-db = passwd

Now edit the passwd file to create a valid login/password credential you will use to access the local repository.

$ vi ~/repositories/svn/local/conf/passwd
[users]
mylogin = mypassword

At this stage, you’ve got the simplest Subversion configuration and it’s time to test it. Launch the Subversion server in test mode and try to connect to it through your favorite SVN client.

$ svnserve -d -r ~/repositories/svn/local

Use the svn://localhost URL and try to create a folder or import an existing project to be sure you are granted the commit permission. If everything works fine, congratulations: you’ve got your own local Subversion repository where you can put under control the code of your project. One more thing you can do is to ensure it’s started when you boot your Mac. I use xinetd to do that. The Subversion service is already mentioned in /etc/services (under the svn alias) so you just have to add a configuration file for xinetd.

$ # kill the existing svnserve daemon
$ killall svnserve
$ sudo vi /etc/xinetd.d/svnserve

# default: on
# Subversion server

service svn
{
    socket_type = stream
    protocol    = tcp
    user        = <mylogin>
    wait        = no
    disable     = no
    server      = /usr/local/bin/svnserve
    server_args = -i -r /Users/<mylogin>/repositories/svn/local
    only_from   = 127.0.0.1
    port        = 3690
}

Replace <mylogin> by your own login. Note that I restrict the access to local clients. Then ask xinetd to reload its configuration.

$ sudo kill -HUP `cat /var/run/xinetd.pid`

and verify that xinetd listens to incoming SVN clients.

$ netstat -an | grep LISTEN | grep 3690
tcp4       0      0  *.3690                 *.*                    LISTEN

You’re done ! Being located on my laptop, I can have it with me anytime, regardless of any connectivity constraints. However, it makes it more difficult to share with other developers. May be Git would be more adequate to fulfill such a requirement.

UPDATE for Snow Leopard (and probably Leopard too)

After migrating to Snow Leopard, I lost the xinetd configuration file because Apple deprecates xinetd in favor of their own startup technology, launchd. Though I had a nice /etc/xinetd.d-migrated2launchd/ directory on my filesystem, it was empty and nothing was actually migrated.

After googling a bit, I figured out I had to configure svnserve for launchd. Here is the org.tigris.subversion.svnserve.plist file I put in place under /Library/LaunchDaemons.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Debug</key>
  <false/>
  <key>GroupName</key>
  <string>mygroup</string>
  <key>Label</key>
  <string>org.tigris.subversion.svnserve</string>
  <key>OnDemand</key>
  <true/>
  <key>Program</key>
  <string>/usr/local/bin/svnserve</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/local/bin/svnserve</string>
    <string>--listen-port=3690</string>
    <string>--listen-host=127.0.0.1</string>
    <string>--inetd</string>
    <string>--root=/Users/<mylogin>/repositories/svn/local</string>
  </array>
  <key>ServiceDescription</key>
  <string>SVN Version Control System</string>
  <key>Sockets</key>
  <dict>
    <key>Listeners</key>
    <array>
    <dict>
      <key>SockFamily</key>
      <string>IPv4</string>
      <key>SockServiceName</key>
      <string>svn</string>
      <key>SockType</key>
      <string>stream</string>
    </dict>
    <dict>
      <key>SockFamily</key>
      <string>IPv6</string>
      <key>SockServiceName</key>
      <string>svn</string>
      <key>SockType</key>
      <string>stream</string>
    </dict>
    </array>
  </dict>
  <key>Umask</key>
  <integer>2</integer>
  <key>UserName</key>
  <string>mylogin</string>
  <key>inetdCompatibility</key>
  <dict>
    <key>Wait</key>
    <false/>
  </dict>
</dict>
</plist>

From here, you can start the service.

$ sudo launchctl load /Library/LaunchDaemons/org.tigris.subversion.svnserve.plist
$ sudo launchctl start org.tigris.subversion.svnserve

References

Subversion Book

  1. Creating and Configuring Your Repository
  2. svnserve, a Custom Server

Kasia in a nutshell Setting up Subversion as an xinetd process (on Linux)

svnserve launchd item for OS X 10.4

5 comments

  1. Anonymous  

    September 24, 2009 at 12:18 PM

    I tried this and ran into a few problems with permissions etc.

    In the end, rather than use this route, I opted to create an Automator workflow to run a shell script to start the server.

    With this saved as an app, you can set it to start at boot through the Users control panel. This may seem a little backward to some people, but it got the job done in a nice easy GUI way that others may prefer.

  2. Laurent Farcy  

    September 24, 2009 at 1:18 PM

    @Anonymous: could you please be a bit more specific about the problems you had, particularly on permissions ?

    I may have forgot a few things I actually did to setup the local SVN repository on my macbook. I could eventually update the article.

    Otherwise, do you intend to publish or describe the Automator script you created. It looks like an elegant solution.

  3. Anonymous  

    July 3, 2010 at 9:29 PM

    Hi! Thanks for the tutorial.

    Unfortunatly I ran into a problem with the snow leopad firewall. When starting svnserve with:
    launchctl load /Library/LaunchDaemons/org.tigris.subversion.svnserve.plist
    I get 'bind(): Operation not permitted' and the console log says:
    Firewall[1333] Deny svnserve binding to 0.0.0.0:3690 proto=6
    Firewall[1333] Deny svnserve binding to :::3690 proto=6

    starting svnserve directly doesn't work either:
    /usr/bin/svnserve -d --root=/Users/svnuser/svn
    svnserve: Can't bind server socket: Operation not permitted


    Disabling the firewall solves the problem, but is obviously not the right way to do it. Any hints?

  4. Kenley  

    May 22, 2014 at 6:42 AM

    Nice Post!

  5. Daisy  

    May 22, 2014 at 6:43 AM

    Great info!

Recent Entries

Recent Comments

Ruby and Rails> Recommended