...making Linux just a little more fun!
"So, let's assume that you're already familiar with SVN..." This might have made a good start for an article that deals with refining and sharpening your SVN-Fu and making you into an SVN Guru. Stephen's article, however, started life as a tip posted to ILUG - and gained a new lease on life when Rick Moen, a member of LG's staff and an ILUG regular, forwarded it to me for possible inclusion in LG. At first, I didn't see this idea as being all that revolutionary - but after an email exchange with Stephen where he explained the finer points to me [1], I came to appreciate it for what it is.
SVN (Subversion, also known as "a compelling replacement for CVS") is a
central part of the LG publication process; after using it for a couple of
years and exploring its various features, I'm definitely a fan. However,
SVN is not an end in itself but an important building block, a flexible
tool. In the case described here, it's used to provide a series of
versioned snapshots of your system - something that would
allow you to "roll it back" to a known-good version (creating a cron job
that would take those snapshots on a regular basis would, of course, be an
obvious complement to this.) In my opinion, that makes a very nice addition
to a system administrator's toolkit - one that's likely to save you untold
grief in a number of situations. That's the kind of ideas and systems I
like to expose to our readers; that, to me, is what makes Linux "just a
little more fun".
-- Ben Okopnik, Editor-in-Chief
So you have all of /etc stored in your SVN repository (say, at file:///root/svn/etc). That works nicely: it's trivially easy to see if any files have changed, you can revert to any previous version, sleep well at night - just great. Then you decide that you should also store /boot in SVN (say, at file:///root/svn/boot). Also great. However, now in order to check if anything has changed, you have to do:
cd /etc; svn status cd /boot; svn status
If you add any more top-level directories to SVN, it quickly becomes a pain to do this. So, you want to store / in SVN also (with the appropriate "svn:ignore" properties set so that all the non-SVN'd top-level dirs don't show up in 'svn status'). If, however, you now try
svn co file:///root/svn/ /
it wont work as SVN will try to also check out /etc and /boot, and will complain that those directories already exist. Hurm. If you try the non-recursive checking
svn co -N file:///root/svn/ /
it will check out file:///root/svn/ into / alright, but /etc and /boot will show up as unknown in "svn status":
fluff# svn status / ? /boot ? /etc
Fixing this requires some minor hackery of the .svn/ special directory. If you open /.svn/entries in a text editor, youll see something like:
<?xml version="1.0" encoding="utf-8"?> <wc-entries xmlns="svn:"> <entry committed-rev="226" name="" committed-date="2006-08-17T22:34:00.835159Z" url="file:///root/svn" last-author="root" kind="dir" uuid="18f6e95b-a6ff-0310-910f-8823210a8ec4" revision="226"/> </wc-entries>
It contains a single <entry ... /> tag, with the name attribute set to "". This is the SVN entry for '/' itself. If you open '/etc/.svn/entries' in a text editor, you'll find a very similar <entry... name=""... /> tag:
<entry committed-rev="25" name="" committed-date="2005-09-22T20:33:37.949298Z" url="file:///root/svn/etc" last-author="root" kind="dir" uuid="18f6e95b-a6ff-0310-910f-8823210a8ec4" revision="25"/>
So, to make SVN consider /etc to be part of the / working directory, what you need to do is this: copy the above <entry.../> tag from /etc/.svn/entries into /.svn/entries, placing it just before the closing </wc-entries> tag. Then, change the 'name' attribute from "" to "etc". The complete finished /.svn/entries file should look like this:
<?xml version="1.0" encoding="utf-8"?> <wc-entries xmlns="svn:"> <entry committed-rev="226" name="" committed-date="2006-08-17T22:34:00.835159Z" url="file:///root/svn" last-author="root" kind="dir" uuid="18f6e95b-a6ff-0310-910f-8823210a8ec4" revision="226"/> <entry committed-rev="25" name="etc" committed-date="2005-09-22T20:33:37.949298Z" url="file:///root/svn/etc" last-author="root" kind="dir" uuid="18f6e95b-a6ff-0310-910f-8823210a8ec4" revision="25"/> </wc-entries>
Now when you check the SVN status of /, it no longer considers /etc to be a foreign object:
fluff# svn status / ? /boot
Bingo. If you repeat the process again for /boot (i.e. copy the <entry... name=""... /> tag from /boot/.svn/entries into /.svn/entries before the closing </wc-entries> tag, and set the name attribute to be "boot") and any other applicable dirs; SVN will then start treating them as proper checked-out subdirs of the working dir.
As your reward, a single 'svn status /' will now check all of the top-level dirs that are stored in Subversion, making it much easier to keep track of things.
[1] Our exchange went something like this:
Ben > > Why not just do 'svn status /etc /boot', or even a little script that Ben > > would read the list of directories in SVN and report on them? E.g., Ben > > Ben > > ------------------------------------------------------------------- Ben > > #!/bin/bash Ben > > Ben > > cd /root/svn Ben > > svn status `echo *|sed 's|\<|/|g'` Ben > > ------------------------------------------------------------------- > Steve > For what i explicitly stated, yes, that's a neat enough solution. Steve > Other solutions that were posted in response on the ILUG list involved Steve > using the "svn:externals" property on / to achieve roughly the same Steve > thing. The downside to doing this is that you lose the benefit of a Steve > cohesive working directory. You can't do atomic commits (you have to Steve > do one per /, /etc and /boot instead). It also doesn't work with Steve > branching etc. And of course you have to remember to run a script Steve > rather than just 'svn status' when you're working on stuff. Steve > Steve > All in all, my solution is probably overkill for most people, i just Steve > thought i'd document it seeing as i discovered it was possible with a Steve > moderate amount of effort, and it makes things nice and elegant for Steve > me, even when i set up svn for /etc before realising that i want it Steve > for other top-level dirs too. Steve > Steve > By all means publish it if you think it's genuinely useful to others, Steve > but i'd perfectly understand if you don't -)
Talkback: Discuss this article with The Answer Gang
Stephen 'Captain Pedantic Pants' Shirley is a quiet student[0] with an appetite for sanely configured, maintainable systems. He was first introduced to Linux in 1996 with RedHat 4.1, and has since progressed through SuSE, Mandrake and Debian, seeking enlightenment. He is now involved in the Ubuntu project, and is the head admin of the University of Limerick computer society (skynet.ie). Currently finishing a MSc through research in the aforementioned UL, he's looking forward to a fulfilling life of bending Unix boxen to his will, whilst striking down inaccuracies wherever he finds them.
[0] It's always the quiet ones...