tags:

views:

1040

answers:

6

EDIT: This question duplicates http://stackoverflow.com/questions/110175/how-to-access-the-current-subversion-build-number#111173 (Thanks for the heads up, Charles!)

Hi there,

This question is similar to http://stackoverflow.com/questions/16248/getting-the-subversion-repository-number-into-code

The differences being:

  1. I would like to add the revision number to Python

  2. I want the revision of the repository (not the checked out file)

I.e. I would like to extract the Revision number from the return from 'svn info', likeso:

$ svn info

Path: .
URL: svn://localhost/B/trunk
Repository Root: svn://localhost/B
Revision: 375
Node Kind: directory
Schedule: normal
Last Changed Author: bmh
Last Changed Rev: 375
Last Changed Date: 2008-10-27 12:09:00 -0400 (Mon, 27 Oct 2008)

I want a variable with 375 (the Revision). It's easy enough with put $Rev$ into a variable to keep track of changes on a file. However, I would like to keep track of the repository's version, and I understand (and it seems based on my tests) that $Rev$ only updates when the file changes.

My initial thoughts turn to using the svn/libsvn module built in to Python, though I can't find any documentation on or examples of how to use them.

Alternatively, I've thought calling 'svn info' and regex'ing the code out, though that seems rather brutal. :)

Help would be most appreciated.

Thanks & Cheers.

+1  A: 

I use a technique very similar to this in order to show the current subversion revision number in my shell:

svnRev=$(echo "$(svn info)" | grep "^Revision" | awk -F": " '{print $2};')
echo $svnRev

It works very well for me.

Why do you want the python files to change every time the version number of the entire repository is incremented? This will make doing things like doing a diff between two files annoying if one is from the repo, and the other is from a tarball..

Jerub
I would imagine BMH doesn't want to use this in every file, but to have a single location that details the current version of the system - look at the bottom right of this page for an example.
Cebjyre
+2  A: 

Python has direct bindings to libsvn, so you don't need to invoke the command line client at all. See this blog post for more details.

EDIT: You can basically do something like this:

from svn import fs, repos, core
repository = repos.open(root_path)
fs_ptr = repos.fs(repository)
youngest_revision_number = fs.youngest_rev(fs_ptr)
JesperE
Yes, but that doesn't give you access to all the logic in svnversion -- which does *exactly* the Right Thing in this kind of situation.
Charles Duffy
+2  A: 

There is a command called svnversion which comes with subversion and is meant to solve exactly that kind of problem.

CesarB
You might amend this to show how one would write the result to a build artifact bundled into a generated egg/package/whatnot, just to be complete and answer both legs of the question (how to calculate the answer, and how to bundle it into your python project).
Charles Duffy
+1  A: 

If you want to have a variable in one source file that can be set to the current working copy revision, and does not replay on subversion and a working copy being actually available at the time you run your program, then SubWCRev my be your solution.

There also seems to be a linux port called SVNWCRev

Both perform substitution of $WCREV$ with the highest commit level of the working copy. Other information may also be provided.

Ber
+3  A: 

Stolen directly from django:

def get_svn_revision(path=None):
    rev = None
    if path is None:
        path = MODULE.__path__[0]
    entries_path = '%s/.svn/entries' % path

    if os.path.exists(entries_path):
        entries = open(entries_path, 'r').read()
        # Versions >= 7 of the entries file are flat text.  The first line is
        # the version number. The next set of digits after 'dir' is the revision.
        if re.match('(\d+)', entries):
            rev_match = re.search('\d+\s+dir\s+(\d+)', entries)
            if rev_match:
                rev = rev_match.groups()[0]
        # Older XML versions of the file specify revision as an attribute of
        # the first entries node.
        else:
            from xml.dom import minidom
            dom = minidom.parse(entries_path)
            rev = dom.getElementsByTagName('entry')[0].getAttribute('revision')

    if rev:
        return u'SVN-%s' % rev
    return u'SVN-unknown'

Adapt as appropriate. YOu might want to change MODULE for the name of one of your codemodules.

This code has the advantage of working even if the destination system does not have subversion installed.

pobk
A: 

Based on CesarB's response and the link Charles provided, I've done the following:

try:
  from subprocess import Popen, PIPE
  _p = Popen(["svnversion", "."], stdout=PIPE)
  REVISION= _p.communicate()[0]
  _p = None # otherwise we get a wild exception when Django auto-reloads
except Exception, e:
  print "Could not get revision number: ", e
  REVISION="Unknown"

Golly Python is cool. :)

Brian M. Hunt