Subversion Versioning

October 18th, 2011

When working with a version control repository, it is often useful to know what version of script we are working on or - in a production environment - which version we are actively using. Subversion provides the facility for incorporating the current version number in a script or source file every time it is committed to the repository. Here's how it can be used:

Adding the Subversion revision to a document

This is pretty easy. We just need to set a subversion property on the document or file and make sure a keyword is included in the document where we want the revision number to appear.
  1. to place a revision number in a document or file, include the text item
    $Rev$
    where the revision number should appear. This will be replaced by text like
    $Rev: 444$
    the next time you commit your script (the number will be different of course)
  2. to tell subversion to update this text item when we commit, we need to set a property on the file; we can do this with a subversion command like
    svn propset svn:keywords "Rev" 
This is elaborated on in the subversion manual and we can include other items of information using keywords such as date, author or id (a combination of other keywords). There are a couple of issues you need to be aware of:
  1. using the
    key / value
    string as normal content in your document can cause the string to be interpreted as a variable which may need disguising e.g. see the perl and bash scripts below
  2. subversion properties can be fragile and are largely invisible i.e properties cannot be set using wildcards (only by individual filename) and it is not easy to see which files have which properties set

A simple bash script to set properties on all files in a folder might look like this

KEYWORDS="Rev Id Date Author"
SVNPROPS="svn propset svn:keywords"
for FILE in *
  do
    if [ -a $FILE ]
    then
      ${SVNPROPS} "${KEYWORDS}" ${FILE}
    fi
  done

Having this information automatically updated in your subversion content is very useful for documentation purposes, if nothing else.

Using $Rev$ in our version number scheme

Now that your documents or scripts have a revision number embedded in them, how can we use this information to construct a document or script version number using the revision. For instance we could have a version number as 1.2.321 where 321 is a subversion revision number. Generally we need to manipulate this information as a string. Here are a few examples in different languages. First, in python:

__version__ = '0.1.' + '$Rev: 21 $'[6:-2]

In this case we are just treating the revision string as a simple string and slicing it. This will create a version number like 0.1.21, And in perl:

my $Rev=0; my $VERSION="$Rev: 21 $Rev"; my @Ver=split(" ",$VERSION); $VERSION="1.2.$Ver[1]";

Here we use several checks to fool perl: we initialise a $Rev variable so we can include the key-name in a regular string (i.e. rather than being embedded in a comment somewhere); now we can just split the string into parts and pick out the value we want. Simples! to give us a version of 1.2.21. And in bash:

REV="\$Rev: 21 $" REV=${REV/\$Rev: /} REV=${REV// \$/} VERSION="2.3.$REV" 

Here we use some regex logic to strip a revision string of the characters we do not want, to give us a version of 2.3.21

Sadly I cannot claim any of these tricks as my own, nor can I provide the original author's names - they have been lost in the mists of time.

 

Running an X-app without an X-server

March 15th, 2011

Hmm, I suppose this sounds like a really daft thing to do - why would you want to run a graphics application on a system without a GUI? Here are a few use cases:

  1. you manage a remote Unix server hosted abroad and of course it is headless and has no use for a Graphics environment
  2. you do have a full-blown Desktop system which has a working Xserver but for some sessions - possibly spawned by a root process - there is no access to the Xserver; you can emulate this with the following sequence entered into an xterm:
    su -
    su - username
    
    i.e. su to root and then to another user - this final session will have lost access to the Xserver
  3. you need to run a graphic tool designed to be called from the command-line; it still needs a GUI environment because it requires access to GUI elements perhaps to generate a graphics file. Lazy programming? Maybe, but that does not fix your problem

In my particular case I needed to run a command that need a GTK environment to generate a graphic image; the command was launched from a Zope application which in turn had been launched as a root service and ultimately it was designed to be run as a facility on a webserver. So I was hit by all these issues.

Ordinarily it should be possible to address issue 2 with some trickery with xhost and Xauthority but even this seems to be non-trivial. I had already identified Xvfb-server as a long-term solution to the first problem and fortunately those good folks on the Interweb were able to point me at a complete solution which does not even require an X server to be running all the time. Instead a virtual server can be created on the fly and brought down when it is finished with. All achieved by the script

xvfb-run

Kudos to darvasan for getting this together and making it easily available. On my SuSE 11.3 system, the script failed to run complaining with

mktemp: too few X's in template `Xauthority'

which was resolved by editing the script as follows:

- AUTHFILE=$(mktemp -p "$XVFB_RUN_TMPDIR" Xauthority) 
+ AUTHFILE=$(mktemp -p "$XVFB_RUN_TMPDIR" Xauthority.XXXXXXXX)

Kudos for that one goes to olesen, an almost anonymous dude on Red Hat Bugzilla.

So having installed the Xvfb server you can now execute the following:

xvfb-run some-daft-gui-script

and provided your script finishes cleanly and doesn't get stuck in a GUI dialogue, you are back at a prompt.

 

Bash Hackery

January 12th, 2011

This is a cunning one I discovered today thanks to someone called vino. If you are a bash geek, you will already know this and, no doubt, use it every day; sadly I don't hack on bash that often.

Problem

Strip-off an extension from a filename in a bash script

Solution

First time I solved this, I used sed, which is fine and so full of potential its a shame not to over-complicate it. Today I found this really neat hack

for FILE in *
  do
    if [ -f $FILE ]
    then
      # name without extension
      NAME=${FILE%.*}
      echo "Filename is ${NAME}"
    fi
  done

much more light-weight; the important bit being:

NAME=${FILE%.*}

I might even be able to remember this one!

Consulting my Bash reference states that

${var%pattern}

gives the value of var after removing pattern from the right

 
 
© 2013 Andy Ferguson