Использовался 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)