Скрипт / утилита для перезаписи всех svn: externals в стволе репозитория - PullRequest
2 голосов
/ 23 июня 2011

Скажите, что вы хотите преобразовать все абсолютные URL-адреса svn: externals в относительные URL-адреса в своем хранилище.

В качестве альтернативы, если прислушаться к подсказке в документах svn: externals («Вы должны серьезно подумать об использовании явных номеров ревизий ...»), может возникнуть необходимость периодически извлекать новые ревизии для внешних ссылок в много мест по всему хранилищу.

Какой лучший способ программно обновить большое количество свойств svn: externals?

Мое решение опубликовано ниже.

1 Ответ

4 голосов
/ 23 июня 2011

Вот мой класс для извлечения деталей из одной строки свойства svn: externals:

from urlparse import urlparse
import re
class SvnExternalsLine:
    '''Consult https://subversion.apache.org/docs/release-notes/1.5.html#externals for parsing algorithm.
    The old svn:externals format consists of:
        <local directory> [revision] <absolute remote URL>

    The NEW svn:externals format consists of:
        [revision] <absolute or relative remote URL> <local directory>

    Therefore, "relative" remote paths always come *after* the local path.
    One complication is the possibility of local paths with spaces.
    We just assume that the remote path cannot have spaces, and treat all other
    tokens (except the revision specifier) as part of the local path.
    '''

    REVISION_ARGUMENT_REGEXP = re.compile("-r(\d+)")

    def __init__(self, original_line):
        self.original_line = original_line

        self.pinned_revision_number = None
        self.repo_url = None
        self.local_pathname_components = []

        for token in self.original_line.split():

            revision_match = self.REVISION_ARGUMENT_REGEXP.match(token)
            if revision_match:
                self.pinned_revision_number = int(revision_match.group(1))
            elif urlparse(token).scheme or any(map(lambda p: token.startswith(p), ["^", "//", "/", "../"])):
                self.repo_url = token
            else:
                self.local_pathname_components.append(token)

    # ---------------------------------------------------------------------
    def constructLine(self):
        '''Reconstruct the externals line in the Subversion 1.5+ format'''

        tokens = []

        # Update the revision specifier if one existed
        if self.pinned_revision_number is not None:
            tokens.append( "-r%d" % (self.pinned_revision_number) )

        tokens.append( self.repo_url )
        tokens.extend( self.local_pathname_components )

        if self.repo_url is None:
            raise Exception("Found a bad externals property: %s; Original definition: %s" % (str(tokens), repr(self.original_line)))

        return " ".join(tokens)

Я использую библиотеку pysvn для рекурсивной итерации всех каталогов, обладающих свойством svn: externals, затем разделяю значение этого свойства на новые строки и воздействую на каждую строку в соответствии с проанализированным SvnExternalsLine.

Процесс должен выполняться при локальной проверке хранилища. Вот как pysvn ( propget ) можно использовать для извлечения внешних данных:

client.propget( "svn:externals", base_checkout_path, recurse=True)

Итерация по возвращаемому значению этой функции и, после изменения свойства в каждом каталоге,

client.propset("svn:externals", new_externals_property, path)
...