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
# 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
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:
# svn cp file:///home/foobsd/mirror/FreeBSD/stable/7 file:///home/foobsd/freebsd7/YYYYMMDD
To generate a diff of a FooBSD branch, simply use svn to compare the FooBSD tree against the most recent import.
# svn diff file:///home/foobsd/freebsd7/YYYYMMDD file:///home/foobsd/stable/7
This is certainly not the only way to maintain a customized version of FreeBSD. However, it is very easy to setup and maintain.