Subversion Installation Notes

I decided to install subversion 1.0 on my system to give it a spin. Here's my system:

Pentium 100
40 MB RAM
4 GB Disk

Quite the power user aren't I?

It's currently running RedHat 9 which I have been keeping up to date with yum.

First let me say that I'm no Linux expert. I know just enough about rpm to get packages installed and removed. I'm sure that I do many things the hard and wrong way from time to time. Here's my story.

Installation

I went to the subversion RedHat 9 download page. I saw the subversion rpm there, and also a ton others. I figured that some of the other packages were prerequisites, but others were not, but possibly of interest to those extra tasks. Not knowing what to download I decided to consult the installation section of the manual. It appears to be a single page with no real information.

Being lazy I just downloaded all of the RPM's with wget:

wget --recursive --level=1 -Psubversion --no-parent
  http://the.earth.li/pub/subversion/summersoft.fay.ar.us/pub/subversion/latest/redhat-9.0/bin/

The total directory size was 37 MB. I didn't first try to install the subversion RPM because I knew I wanted to use it as an apache mod so I first tried to install apache.

rpm -i httpd-2.0.48-3.i386.rpm
error: Failed dependencies:
libapr-0.so.0 is needed by httpd-2.0.48-3
libaprutil-0.so.0 is needed by httpd-2.0.48-3

I satisfied these by installing these two RPM's:

rpm -i apr-0.9.5-0.2.i386.rpm
rpm -i apr-util-0.9.5-0.1.i386.rpm

and then installed apache:

rpm -i httpd-2.0.48-3.i386.rpm

I then got cold feet, not just wanting to just install the subversion RPM like I did apache so I did one more web search and found these instructions. They were for version 0.29 of subversion but they provided some guidance. 

rpm -i httpd-manual-2.0.48-3.i386.rpm
rpm -i mod_ssl-2.0.48-3.i386.rpm swig-1.3.19-1.1.i386.rpm

I got about 100 of these messages printed to the console:

warning: user david does not exist - using root
warning: group david does not exist - using root

I have no idea what they mean, but the install seemed to work alright

rpm -i neon-0.24.4-1.i386.rpm
rpm -i subversion-1.0.0-1.rh90.i386.rpm
rpm -i subversion-server-1.0.0-1.rh90.i386.rpm
rpm -i subversion-tools-1.0.0-1.rh90.i386.rpm
rpm -i subversion-python-1.0.0-1.rh90.i386.rpm

OK, I think that it's installed now. I then started apache:

/etc/init.d/httpd start

which produced this output:

Starting httpd: httpd: Could not determine the server's fully qualified domain n
ame, using 127.0.0.1 for ServerName
                                                           [  OK  ]

This was alright as far as I was concerned since this machine was not on the public internet and I am planning on getting remote access via ssh. I then fired up my browser and surfed over the my new apache server and the default page came up just fine.

Running subversion (or so I think)

OK I think it's installed - now to get some source in the repository. I'm coding on Windows so I went to the Windows download section looking for the client program. I downloaded and started setup.exe program, but it wasn't clear if I was getting the server, client, or both - my guess was both. I didn't want the server and was afraid of what that configuration might do to my system so I instead opted to download the ZIP archive of subversion.

I extracted the archive and moved the svn-win32-1.0.0 folder to my "C:\Program Files" folder. After opening this folder I then opened the README.txt file which referred me to http://svn.collab.net/repos/svn/trunk/INSTALL. I wish I had this information earlier. 

Installation (cont.)

Now that I have some instructions on configuring my apache server I continue on. I add this line to the bottom of my /etc/httpd/conf/httpd.conf file (I later learned this to put this in the /etc/httpd/conf.d/subversion.conf):

LoadModule dav_svn_module modules/mod_dav_svn.so

The instructions also say:

Note that if mod_dav was compiled as a shared object (instead of statically linked directly to the httpd binary), you'll need a similar LoadModule statement for it, too.

But I saw this line in the config file:

LoadModule dav_module modules/mod_dav.so

so I assume that this is already done.

I then specified my repository path:

<Location /repos>
  DAV svn
  SVNPath /usr/local/src/svnroot
</Location>

There was a very good section on httpd authentication which I decided to setup after subversion was fully configured and working.

I then restarted my web server:

/etc/init.d/httpd restart

I tried to browse to what I think is the subversion url: http://machine/repos but I got the dreaded 404 error. I know that I haven't yet setup the repository and maybe this is the reason. Let's give that a try.

Running subversion (take #2)

I added subversion to my path and typed svn -h. I got the following:

$ svn -h
usage: svn <subcommand> [options] [args]
Type "svn help <subcommand>" for help on a specific subcommand.

Most subcommands take file and/or directory arguments, recursing
on the directories.  If no arguments are supplied to such a
command, it will recurse on the current directory (inclusive) by
default.

Available subcommands:
   add
   blame (praise, annotate, ann)
   cat
   checkout (co)
   cleanup
   commit (ci)
   copy (cp)
   delete (del, remove, rm)
   diff (di)
   export
   help (?, h)
   import
   info
   list (ls)
   log
   merge
   mkdir
   move (mv, rename, ren)
   propdel (pdel, pd)
   propedit (pedit, pe)
   propget (pget, pg)
   proplist (plist, pl)
   propset (pset, ps)
   resolved
   revert
   status (stat, st)
   switch (sw)
   update (up)

Subversion is a tool for version control.
For additional information, see http://subversion.tigris.org/

OK, now let's try to add a file to the repository. I went to my src folder and made a new folder named "svntesting". In it a created hello.c (a hello world program). I then tried to add it to the repository:

svn import svntesting http://ghen/repos

It failed with this output:

svn: PROPFIND request failed on '/repos'
svn: PROPFIND of '/repos': 405 Method Not Allowed (http://ghen)
svn: Your commit message was left in a temporary file:
svn:    'svn-commit.tmp'

I went to look at my httpd.conf file and noticed that the location configuration specification was not there. I must have forgotten to save this file. I fixed this and retried my import command. This time I got the following output:

svn: PROPFIND request failed on '/repos'
svn:
Could not open the requested SVN filesystem

svn: Your commit message was left in a temporary file:
svn:    'svn-commit.4.tmp'

Now I never created a repository, and that's probably what's lacking. After consulting the manual I noticed the chapter on creating a repository. I read this chapter and then ran the command on the server to create the repository:

svnadmin create /usr/local/src/svnroot

Unfortunately it didn't work. The output was:

svn: Berkeley DB error while creating environment for filesystem /usr/local/src/
svnroot/db:
Function not implemented

I did some Google searching and found this FAQ entry. I'm guessing that because I used yum to upgrade my kernel I wound up getting a new kernel without support for POSIX threads .

OK, now here remember this point in time since I suspect that this is where I start to do something really stupid. Later on today I'm going to wish I could go back here and turn right instead of left.

Well enough of that, back to my problem. Here are the kernel RPM's installed:

[root@ghen root]# rpm -qa | grep kernel
kernel-2.4.20-8
kernel-2.4.20-28.9
kernel-pcmcia-cs-3.1.31-13
kernel-mppe-2.4.20-8
kernel-2.4.20-24.9

And here's what's on the CDROM:

kernel-2.4.20-8.athlon.rpm
kernel-2.4.20-8.i586.rpm
kernel-2.4.20-8.i686.rpm
kernel-bigmem-2.4.20-8.i686.rpm
kernel-BOOT-2.4.20-8.i386.rpm
kernel-pcmcia-cs-3.1.31-13.i386.rpm
kernel-smp-2.4.20-8.athlon.rpm
kernel-smp-2.4.20-8.i686.rpm
kernel-doc-2.4.20-8.i386.rpm
kernel-source-2.4.20-8.i386.rpm
kernel-utils-2.4-8.29.i386.rpm

What do I downgrade? I have no idea where to go from here? Well so much for downgrading the kernel. Maybe I can rebuild db4:

[root@ghen root]# rpm -qa *db4*
db4-4.0.14-20
db4-devel-4.0.14-20
db4-utils-4.0.14-20

I went to www.rpmfind.net and found this RPM: db4-4.0.14-20.src.rpm. Hopefully I can just rebuild this. Man I vaguely remember installing and building a source RPM about three years ago, so here we go.

I believe that I'm supposed to build it like this:

rpm --rebuild db4-4.0.14-20.src.rpm

Well that didn't work It said that "--rebuid" was an unknown option. Other web searches suggested that this might be the right way to install it:

rpm -ivh db4-4.0.14-20.src.rpm

This happened so quickly that I question if it did anything. I tried the svnadmin again and it failed as before. I tried it again as root, but still the same. It looks like it just extracts the source into /usr/src/redhat/RPMS.

Hmm... There were a few references to rpmbuild. I'm guessing that this new program has replaced the deprecated --rebuild option in rpm. I give it a try:

[root@ghen chris]# rpmbuild --rebuild db4-4.0.14-20.src.rpm
Installing db4-4.0.14-20.src.rpm
error: Failed build dependencies:
        jdkgcj >= 0.1.0 is needed by db4-4.0.14-20

I found this package on disk 2.

rpm -i jdkgcj-0.2.3-5.i386.rpm

I get this output:

warning: jdkgcj-0.2.3-5.i386.rpm: V3 DSA signature: NOKEY, key ID db42a60e
error: Failed dependencies:
        gcc-java = 3.2.2 is needed by jdkgcj-0.2.3-5

OK, so I try to install this:

rpm -i gcc-java-3.2.2-5.i386.rpm

but get this output:

error: Failed dependencies:
        libgcj-devel >= 3.2.2 is needed by gcc-java-3.2.2-5

so then I:

rpm -i libgcj-devel-3.2.2-5.i386.rpm

OK, that worked and my dependencies should not be met - now undo my stack:

rpm -i gcc-java-3.2.2-5.i386.rpm

and now

rpm -i jdkgcj-0.2.3-5.i386.rpm

And now to try to build the RPM again:

rpmbuild --rebuild db4-4.0.14-20.src.rpm

It worked for about five minutes and eventually failed with this message:

checking for mutexes... configure: error: unable to find POSIX mutex interfaces
error: Bad exit status from /var/tmp/rpm-tmp.35013 (%build)


RPM build errors:
    Bad exit status from /var/tmp/rpm-tmp.35013 (%build)

Darn. I was hoping that the configuration program would auto detect that there was no support for POSIX threads and use an alternative.

I called my friend Steve and he suggested that the reason that there are multiple kernels installed is just that - there are several kernels, but that there is only one active kernel in the bootloader. I'm going to reboot the system and see if I can select another kernel. I first tried selecting the 2.4.20-8 kernel, but svnadmin still didn't work, so I rebooted again. I tried all four available boot configurations and they all failed identically so I went back to the default kernel.

My next step is to try to modify the source to db4 so that it doesn't require POSIX threads. I found a guide to rebuilding source RPM's. These are actually a bit old and are written for those wanting to port RPM's to PPC, but the instructions were good and easy to interpret. I went to /usr/src/redhat/SPECS and commented out this line in db4.spec line 2:

#%define nptl_arches %{ix86}

And also this starting on line 167:

#%ifarch %{nptl_arches}
#       --enable-posixmutexes \
#%endif

I then rebuilt the source using this command:

rpmbuild -bc db4.spec

Which worked!

I then recreated the package continuing to use the instructions mentioned above.

I now had a package in the /usr/src/redhat/RPMS/i386 folder. I tried to install it like this:

rpm -ihv db4-4.0.14-20a.i386.rpm

Unfortunately this didn't work because I got this error:

file /lib/libdb-4.0.so from install of db4-4.0.14-20a conflicts with fil
e from package db4-4.0.14-20
        file /usr/lib/libdb_cxx-4.0.so from install of db4-4.0.14-20a conflicts
with file from package db4-4.0.14-20

So I tried an upgrade instead

[root@ghen i386]# rpm -Uhv db4-4.0.14-20a.i386.rpm
error: Failed dependencies:
        db4 = 4.0.14-20 is needed by (installed) db4-devel-4.0.14-20
        db4 = 4.0.14-20 is needed by (installed) db4-utils-4.0.14-20

My guess is that it's because I 

I think that I wan to do this, but am not sure

rpm -Uhv --nodeps db4-4.0.14-20a.i386.rpm

I give it a try. Well it seemed to work. 

rpm -q db4

now returns

db4-4.0.14-20a

Great. I now run:

svnadmin create /usr/local/src/svnroot

Which now runs and doesn't print out any errors!

I then went back and tried to add a file to the repository:

svn import svntesting http://ghen/repos

which failed with this message:

svn: PROPFIND request failed on '/repos'
svn:
Could not open the requested SVN filesystem

svn: Your commit message was left in a temporary file:
svn:    'svn-commit.7.tmp'

Now this looks like a permissions problem. I then went to /usr/local/src and ran this command:

chmod -R ugo+rw svnroot

I tried the svn import again and it worked!

I browsed over to http://ghen/repos and found hello.c at the top level (oops) I should instead have imported it like this:

svn import svntesting http://ghen/repos/svntesting

Converting my CVS Repository

With a good backup of my cvs repository I decided to use cvs2svn to convert my CVS repository to subversion. The cvs2svn script seemed to be the most recommended script, but it has this disclaimer at the top of its README file:

****************************** Warning ******************************
   *                                                                   *
   * cvs2svn.py is not "1.0 quality" yet.  While it has successfully   *
   * converted many repositories (including their branches and tags),  *
   * for others it has either failed to complete the conversion, or    *
   * converted the data in an unexpected or subtly wrong way.  It is   *
   * also not well-packaged yet.  For example, there's no easy way to  *
   * install it on your system: right now the recommended way to run   *
   * cvs2svn.py is right out of this directory, so it can find the     *
   * 'rcsparse' module on which it depends (see subdir rcsparse/).     *
   *                                                                   *
   *********************************************************************
cvs2svn.py --create -s /usr/local/src/svnroot /usr/local/src/cvsroot

Which when I ran produced this error:

-bash: cvs2svn.py: command not found

I added the current working directory to my path like this:

export set PATH=$PATH:.

And reran cvs2svn.py which produced a ton of output and finally failed with this output:

----- pass 3 -----
----- pass 4 -----
creating repos '/usr/local/src/svnroot'
svn: Repository creation failed
svn: Could not create top-level directory
svn: '/usr/local/src/svnroot' exists and is non-empty
Command failed: "svnadmin create /usr/local/src/svnroot"

Apparently (as the create option suggests) you cannot have an existing repository. I moved aside the new one I created and tried cvs2svn.py again. It took a while on my system but it seemed to work without any errors.

I then tried to checkout one of my projects from subversion:

svn co http://ghen/repos/trunk/TinyProj 

It got all my files, but hung at the end of the checkout with this error:

svn: REPORT request failed on '/repos/!svn/vcc/default'
svn: REPORT of '/repos/!svn/vcc/default': Could not read chunk size: connection
timed out. (http://ghen)

I then tried to surf to http://ghen/repos and the browser hung. I then restarted apache on my server machine:

[root@ghen log]# /etc/init.d/httpd restart
Stopping httpd:                                            [FAILED]
Starting httpd: httpd: Could not determine the server's fully qualified domain n
ame, using 127.0.0.1 for ServerName
                                                           [  OK  ]

Notice the failure shutting it down. It was already running so something strange is happening. I then brought up the browser again and got this error message:

<m:human-readable errcode="160029">Could not open the requested SVN filesystem</m:human-readable>

I web search turned up this reply to another post:

It's saying there was a fatal error, and that you need to recover the database. This means stop all access to the repository (i.e., stop the apache process), and run 'svnadmin recover' on the repository. If all goes well, it'll print out the youngest revision in the repository when it's complete. After that, you need to ensure that your permissions are still correct, and try again.

I then ran:

svnadmin recover /usr/local/src/svnroot

This completed successfully with this output:

Please wait; recovering the repository may take some time...

Recovery completed.
The latest repos revision is 415.

I then restarted httpd and surfed over to my repository. My browser hung and after two minutes I closed the window.

I restarted apache and tried another checkout.

svn co http://ghen/repos/trunk/TinyProj

and got this output:

svn: PROPFIND request failed on '/repos/trunk/TinyProj'
svn:
Could not open the requested SVN filesystem

Grrrrr!!!!

OK. I changed the owner/group to apache/apache for the repository at /usr/local/src/svnroot. Even though all these files had full user/group/other access. Now the checkout worked and I can surf the repository.

Repository Comparisons

Now that everything appears to be setup properly I wanted to do a fresh checkout of my CVS repository and compare it to a fresh checkout of my subversion repository. Here's what I found.

First off the EOL styles of all of my files was UNIX stile, I guess because my subversion server is running on a Linux box. A Google search pointed me to svn:eol-style. The manual has a section on this. As I currently understand it I must set this property on each file.

Apparently this is a problem that many users of cvs2svn have encountered and I would call it an unimplemented feature. A user named Stefan Haller has submitted a patch which was committed in release r870 to fix this problem.

I diff'ed a freshly checked out subversion repository against a fresh CVS checkout and the only differences (ignoring differing EOL styles) were the CVS version numbers for the few files which had them. So a line like in the CVS file:

* $Header: /usr/local/src/cvsroot/menu_flex.cpp,v 1.1.1.1 2003/12/09 05:32:54 chris Exp $

Turned into this when committed into subversion

* $Header: /usr/local/src/cvsroot/menu_flex.cpp,v 1.1 2003/12/09 05:32:54 chris Exp $

Overall thoughts

I guess that if I had a totally stock RedHat installation then this would have gone much smoother. Still there seem to be some permissions requirements which aren't set automatically by svnadmin and were not evident in the documentation.

The speed is quite a bit slower compared to CVS. I imaging that somebody on a more modern system won't even notice the speed difference. 

I'm a bit worried that I needed to do a database recover after only a few operations. This may have been unnecessary, but for sure one of two things happened: it was necessary, or I did it it because I thought it was necessary. I'm neither the smartest or stupidest programmer out there and I'd like to think that if I'm having these difficulties then others will too.

I am impressed with the syntax. I think that CVS users like the transition.

Further Notes

More on cvs2svn

To run with the Stefan Haller patch on your entire CVS repository do this:

cvs2svn.py --mime-types=mime.types --set-eol-style --username=chris 
  -s /usr/local/src/svnroot /usr/local/src/cvsroot

Here is my mime.types file.

My CVS repository was a collection of my personal projects. I'm still not sure if I want them in a single repository, or each in their own repository. I'm leaning toward different repositories. The cvs2svn script didn't handle this directly so I wrote a very simple perl script to front-end cvs2svn and call it multiple times - for each project in my CVS repository.

Creating Repositories

Let's say I have a new project named "Differ" (for which I want to create a new repository)

On the server machine run this command:

svnadmin create /usr/local/src/svnroot/Differ

Modify permissions of repository:

chown -R apache Differ/
chgrp -R apache Differ/

I then went and modified /etc/httpd/conf.d/subversion.conf

<Location /Differ>
  DAV svn
  SVNPath /usr/local/src/svnroot/Differ
</Location>

Restarted Apache:

apachectl restart

On the client machine

svn checkout http://ghen2/Differ

I now copied over the files from my saved Differ folder where I had originally written my program and then did an svn add, and an svn commit. Ok. I'm sorta lying: I used TortoiseSVN.

Properties

To see the file properties:

svn proplist --verbose *

This seems to die on the first non version controlled file.

To set the properties:

svn propset svn:mime-type image/ico *.ico