Skip to content

Script to gather the svn:externals.

February 26, 2008

Today I got tired of going through a set of subdirectories that all are svn:externals and pasting the urls into an EXTERNALS.txt file. So I wrote a script to do it instead, using pysvn.

It preserves comments in an EXTERNAL.txt file (and the file name if it’s called something else), but stacks the comments in the beginning. It also will store the revision number you used if there has been modifications, so do an svn up first. I realize there is a better way to check that then the one I use, and I just realized it does not actually add the EXTERNALS.txt to the repository, but those improvements are left as an exercise to the reader.😉 )

Here ya go:

import os
import tempfile
import pysvn

externals_comment = """# If you want to change externals, modify the relevant line in this
# file. Afterwards, run:
# svn propset svn:externals -F EXTERNALS.txt .

client = pysvn.Client()
tempdir = tempfile.mkdtemp()
repo_revisions = {}
externals = []

filenames = os.listdir('.')
for filename in filenames:
    if os.path.isdir(filename):
        info =
        if info is None:
        repo = info.repos
        if not repo in repo_revisions.keys():
            # Get the last revision for the used repository:
            repoinfo = client.info2(info.url, recurse=False)
            repo_revisions[repo] = repoinfo[0][1].rev
        if repo_revisions[repo] != info.revision:
            # Check if they differ:
            diff = client.diff(tempdir, info.url, info.revision,
                               info.url, repo_revisions[repo])
            if diff:
                use_revision = info.revision.number
                use_revision = None

            externals.append((filename, use_revision, info.url))

# OK, so lets see if there is an EXTERNALS.txt file:
externals_filename = None
for filename in ('svn:externals', 'externals.txt', 'EXTERNALS.txt'):
    if os.path.exists(filename):
        externals_filename = filename

if externals_filename is not None:
    # Suck in the comments:
    text = open(externals_filename).readlines()
    text = [x for x in text if x.strip().startswith('#') or not x.strip()]
    externals_comment = ''.join(text)
    externals_filename = 'EXTERNALS.txt'

external_text = externals_comment
for dir, revision, url in externals:
    if revision is not None:
        external_text += '%s -r%s %sn' % (dir, revision, url)
        external_text += '%s %sn' % (dir, url)

open(externals_filename, 'w').write(external_text)
client.propset('svn:externals', external_text, '.')

From → python

  1. Rob Miller permalink

    You might also consider checking out externalator (, a tool developed by one of my TOPP cohorts which gives you a command line tool for managing svn bundles.

  2. Sure. Could you maybe have a description on pypi that tells me a little about it and hwat it does? “svn bundle manager” is not exactly very exhaustive.😉

  3. Rob Miller permalink

    Er, yeah, I guess there’s not much info there. I’ll pass your request on to the author.

    Even the README is a bit incomplete, but it does have some simple usage information:

    The short story is that it’s a command line utility that can be used inside an svn bundle checkout, to examine, add, remove, or freeze (i.e. peg to the current revision) the bundle’s externals. It negates the need for an EXTERNALS.txt file altogether.

  4. Rob Miller permalink

    urgh… here’s the link above w/o the trailing dot:

  5. Hmm, that’s interesting. That’s one part of the functionality I need for a release manager.

  6. And on another note, I notice that this, just as bundleman, handles svn not by PySVN or similar, but by calling svn commands as processes and massaging the output.

    Is there a good reason for that?

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: