Using svk and svn to Maintain a FooBSD

Several of the companies I have worked for have used a modified version of FreeBSD for various tasks. Generally these modified versions of FreeBSD are given their own name. Hence “FooBSD”.

My first attempt at doing this consisted of leaving local patches in a CVS checkout and dealing with conflicts when updating from one branch to another. Fortunately, there were very few patches in this particular FooBSD. However, the approach of just keeping patches around does not scale well.

My next experience was far more workable. In this case, my employer’s FooBSD lived in an actual source code repository as a branch of FreeBSD. This setup was very nice and also allowed this particular FooBSD to span many different versions of FreeBSD. However, the actual system to manage this was a bit complex and not easy to duplicate. It relies on custom scripts to import periodic snapshots of various branches of the FreeBSD source tree as a vendor sources into the source code repository. It also predates FreeBSD’s switch from CVS to Subversion.

I recently changed jobs. My new employer was maintaining a few modifications as local patches. I wanted to store these changes (along with future changes) as a branch of FreeBSD. I did not want to write and maintain a complex set of scripts to do this, however. After some investigation, I found that I could use svk to easily setup a mirror of FreeBSD’s Subversion repository in a local Subversion repository and to create branches of FreeBSD to hold my FooBSD changes.

Initial svk Setup

The first thing to do is configure svk to create a new Subversion repository. In this case, I am going to create the repository in the /home/foobsd directory. The first parameter to the depotmap command below is a nickname for this new repository that is used in svk commands.

# svk depotmap foobsd /home/foobsd

Next, I tell svk that it should mirror the FreeBSD source code repository into the mirror/FreeBSD path within my new repository. Note that this just establishes a mapping similar to a branch specification in Perforce. It does not copy any data into my local repository.

# svk mirror svn://svn.FreeBSD.org/base /foobsd/mirror/FreeBSD

Note: You may not want to mirror the entire FreeBSD repository in this manner. You probably only need to mirror certain branches of FreeBSD. I believe you can do that by mirroring each branch to a separate path in your local repository.

Finally, before I can create a branch of FreeBSD, I need to perform an initial update of my local FreeBSD mirror. This is done via svk’s sync command.

# svk sync /foobsd/mirror/FreeBSD

Note: This may take a long time. There may be ways to save a lot of time and bandwidth using by pulling from a local SVN mirror instead or using a seed. I couldn’t get the seed stuff to work the way I wanted and hadn’t thought of using a local svnsync’d mirror when I first set this up, however.

Creating a Branch

Once the initial sync has completed, you are ready to create a new branch of FreeBSD. The command below creates a branch of FreeBSD 7.x.

# svk cp /foobsd/mirror/FreeBSD/stable/7 /foobsd/stable/7

You can now use this branch using regular Subversion commands if you wish. Recall that /foobsd in svk maps to the Subversion repository in /home/foobsd. Thus, to checkout the FooBSD 7.x branch, simply use this svn command:

# svn co file:///home/foobsd/stable/7

You can commit your local changes to this branch using svn. You can also create new branches off of this branch using svn as well.

Merging Changes from FreeBSD

Eventually you are going to want to pull in changes from FreeBSD to your local FooBSD branch. svk makes this fairly painless. Merging consists of two steps. First, you need to use svk sync to update your local mirror of the FreeBSD repository.

# svk sync /foobsd/mirror/FreeBSD

Second, you need to merge the changes into your local branch. Note that this only merges the changes that have been synced into your local FreeBSD mirror. It does not pull changes directly from the FreeBSD repository.

# svk smerge /foobsd/mirror/FreeBSD/stable/7 /foobsd/stable/7

svk will first prompt you for the log message. It will then begin merging changes and will prompt you to resolve any conflicts. Finally, it will commit the result. If you wish to check for conflicts without doing an actual merge, you can pass the -C argument to smerge.
As an additional step, I like to tag each import that I merge into my FooBSD so I can easily generate diffs later. I do this using a plain svn copy of the FreeBSD mirror branch:

Generating Diffs

Conclusion

This is certainly not the only way to maintain a customized version of FreeBSD. However, it is very easy to setup and maintain.

This entry was posted
on Tuesday, May 26th, 2009 at 9:59 pm and is filed under FreeBSD.
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

My understanding is that SVK, Git, and Mercurial are all supposed to do this sort of task fairly well. As I noted in the conclusion, SVK isn’t the only way to do this. One possible advantage of the SVK approach is that if you are already familiar with SVN, then this approach allows you to use a tool you are already familiar with for most of your day-to-day tasks.

An update to this, I’ve recently added support to the release Makefile for using SVN with “make release”. One would do ‘make SVNROOT=file:///home/foobsd SVNBRANCH=stable/7′ with those changes to build a release of FooBSD 7.x.