Получение измененных файлов из SVN

Использовался Python 2.4 и модуль pysvn (устанавливается пакетом python-svn). Большую часть кода занимает разбор командной строки. К сожалению, модуль pysvn не умеет указывать ревизии аналогично тому, как это сделано в клиенте командной строки svn. Для решения этой задачи пришлось написать некрасивую функцию.

Дальше все просто. Получается список изменений с измененными файлами. Строится множество измененных файлов. Получается тело каждого файла. Создается каталог и содержимое файла копируется в него. Исключения перехватываются, чтобы получить по возможности больше файлов.

Файл /home/gelin/bin/svn-get.py:

#!/usr/bin/python
# (c) 2007 Denis Nelubin aka Gelin
# This script gets files from SVN repository changed between (inclusive) specified revisions

import sys
import pysvn
import time
import os
import os.path

SVN_REPOS = "file:///home/gelin/svn"


def revision_from_string(arg):
    """ Creates revision from command line argument as it's done by svn client """
    #check for date
    DATE_FORMAT = "{%Y-%m-%d}"
    try:
        return pysvn.Revision(pysvn.opt_revision_kind.date,
                time.mktime(time.strptime(arg, DATE_FORMAT)))
    except ValueError:
        pass
    #check for integer
    try:
        return pysvn.Revision(pysvn.opt_revision_kind.number,
                int(arg))
    except ValueError:
        pass
    #other special values
    return pysvn.Revision(getattr(pysvn.opt_revision_kind, arg.lower(),
             pysvn.opt_revision_kind.unspecified))  #get revision kind by name


if len(sys.argv) < 3:
    print "Usage: %s PATH_IN_REPOSITORY FROM_REVISION TO_REVISION" % sys.argv[0]
    sys.exit(1)

repos_path, from_rev = sys.argv[1:3]
from_rev = revision_from_string(from_rev)
if from_rev.kind == pysvn.opt_revision_kind.unspecified:
    from_rev = pysvn.Revision(pysvn.opt_revision_kind.number, 0)
if len(sys.argv) >= 4:
    to_rev = sys.argv[3]
else:
    to_rev = "HEAD"
to_rev = revision_from_string(to_rev)
if to_rev.kind == pysvn.opt_revision_kind.unspecified:
    to_rev = pysvn.Revision(pysvn.opt_revision_kind.head)

client = pysvn.Client()

log = client.log(SVN_REPOS + "/" + repos_path,
        discover_changed_paths=True,
        revision_start=from_rev,
        revision_end=to_rev)

files = set()

for record in log:
    for path in record["changed_paths"]:
        if (path["action"] in ("A", "M")):  #file is added or modified
            files.add(path["path"])

for file in files:
    print file
    try:
        os.makedirs(os.path.dirname("." + file))
    except OSError:
        pass
    try:
        content = client.cat(SVN_REPOS + file, revision=to_rev)
        f = open("." + file, "w")
        f.write(content)
        f.close()
    except (pysvn.ClientError, IOError), e:    #don't break execution
        print "WARNING: " + str(e)